1. Load Data

library(readxl)
library(tidyr)
library(dplyr)
library(sjPlot)
library(ggplot2)
library(plotly)

source("../../Accelerate/notebooks/custom_functions.R")

teams = read_excel("../data/O17ClimateGender_teamformation.xlsx")
#teams = lapply(teams, as.character)

assesment = read_excel("../data/O17ClimateGender_assessment.xlsx")

load("../../Accelerate/processed data/registration.RData")

map = read.csv("../../Accelerate/data/team_users_hashed.csv", stringsAsFactors = FALSE)
colnames(map) = c("Team", "ID", "Hash", "Mentors")

reg = merge(reg, map[,c("Team", "Hash")], by.x = "ID", by.y = "Hash")

reg_map = c("A2: Women & Technology Against Climate Change" = "T6: Women & Technology Against Climate Change", "B2: TEAM FOILED" = "T3: TEAM FOILED", "C1: Andapé Institute" = "T13: Andapé Institute", "C3: WOMER" = "T5: WOMER", "A5: Donate Water Project" = "T9: DonateWater", "B5: Rights of Climate" = "T11: Rights of Climate", "B3: Eco Winners" = "T14: Eco Winners", "B4: Women 4 Sustainable World" = "T12: Women 4 Sustainable World", "A1: Up Get App/CitiCERN" = "T7: UpGet app - CitiCERN Project", "B1: Water Warriors" = "T10: Water Warriors", "C2: PAM" = "T4: PAM", "C4: Climate Gender Justice" = "T8: Climate Gender Justice", "A3: Rhythm of Bamboos" = "T1: SDesiGn (Old name: Rhythm of Bamboos)", "C5: Ashifa Nazrin" = "C5: Ashifa Nazrin", "A4: Flood Rangers" = "T2: Flood Rangers")

reg_map = data.frame(old_name = names(reg_map), new_name = reg_map)
reg = merge(reg, reg_map, by.x = "Team", by.y = "old_name", all.x = TRUE)

write.csv(unnest(reg, cols = c("communication")), file = "../processed data/reg_edited.csv")

map = merge(map, reg_map, by.x = "Team", by.y = "old_name", all.x = TRUE)
map$new_name = as.character(map$new_name)
map$new_name[map$Team == "Organizing Team"] = "Organizing Team"

size = map %>% group_by(new_name) %>% summarise(size = n())

jury_scores = read.csv("../data/assessment_sheet1.csv", stringsAsFactors = FALSE)

jury_scores_avg = jury_scores %>% group_by(Choose.the.Team) %>% summarise(mean_novelty = mean(Novelty..Is.the.pitch.based.on.a.new.idea.or.concept.or.using.existing.concepts.in.a.new.context., na.rm = TRUE), mean_relevance = mean(Relevance..Is.the.solution.proposed.relevant.to.the.challenge.or.potentially.impactful.., na.rm = TRUE), mean_feasibility = mean(Feasibility..Is.the.project.implementable.with.reasonable.time.and.effort.from.the.team., na.rm = TRUE), mean_crowdsourcing = mean(Crowdsourcing..Is.there.an.effective.crowdsourcing.component., na.rm = TRUE), mean_presentation = mean(How.would.you.rate.this.team.s.overall.presentation.skills.during.this.pitch., na.rm = TRUE))

jury_scores_avg = jury_scores_avg[-c(1),]

Outcome Variable


outcome = assesment[,c("Team", "Total", "Weekly Evaluation", "Commitment", "Attendance", "Deliverables", "Final Pitch", "Data Collection and NSO", "Appropriateness of Methodology")]
outcome = merge(outcome, teams[,c("Team Name", "Stage", "Type")], by.x = "Team", by.y = "Team Name", all.x = TRUE)
outcome$Stage = factor(outcome$Stage, levels = c("Evaluate", "Accelerate", "Refine"), ordered = TRUE)

outcome = merge(outcome, jury_scores_avg, by.x = "Team", by.y = "Choose.the.Team", all.x = TRUE, all.y = TRUE)
outcome$stage_progressed = 0
outcome$stage_progressed[outcome$Stage == "Accelerate"] = 1
outcome$stage_progressed[outcome$Stage == "Refine"] = 2

outcome$formation = 0
outcome$formation[outcome$Type == "Algorithm"] = 1

Surveys and Interactions


load("../../Evaluate/processed data/surveys.RData")

inter = interactions[,c(1,8,2,3)]
inter = merge(inter, map[,c("ID", "new_name")], by.x = "user_id", by.y = "ID", all.x = TRUE)
colnames(inter) = c("From", "To", "Survey_id", "Question", "From_team")
inter = merge(inter, map[,c("ID", "new_name")], by.x = "To", by.y = "ID", all.x = TRUE)
colnames(inter)[colnames(inter) == "new_name"] = "To_team"

inter = inter[!inter$To %in% c(34), c(2,1,3,4,5,6)]

teams = merge(teams, size, by.x = "Team Name", by.y = "new_name", all.x = TRUE)

g_int = graph_from_data_frame(inter, directed = FALSE, vertices = map[,c(2,1,3,4,5)])

g_int_teams = graph_from_data_frame(inter[,c(5,6,1:4)], directed = FALSE, vertices = teams)
E(g_int_teams)$weight = 1
g_int_teams_simp = simplify(g_int_teams, remove.loops = FALSE)

write.csv(inter, "../processed data/survey_interactions.csv")

  1. Survey Metrics
  1. Interactions

#Known Before

g_kb = subgraph.edges(g_int_teams, eids = E(g_int_teams)[E(g_int_teams)$Question == "Which of these people did you know personally before?"], delete.vertices = FALSE)
E(g_kb)$weight = 1
g_kb_simp = simplify(g_kb, remove.loops = FALSE)

g_kb_users = subgraph.edges(g_int, eids = E(g_int)[E(g_int)$Question == "Which of these people did you know personally before?"], delete.vertices = FALSE)

team_kb = data.frame()

for (i in V(g_kb_simp)$name)
{
  g = induced_subgraph(g_kb_users, vids = V(g_kb_users)[V(g_kb_users)$new_name == i])
  
  intra = length(E(g_kb_simp)[get.edge.ids(g_kb_simp, vp = c(i, i))])
  org = length(E(g_kb_simp)[get.edge.ids(g_kb_simp, vp = c(i, "Organizing Team"))])
  inte = degree(g_kb_simp, v = i) - (2*intra) - org
  size = V(g_kb_simp)$size[V(g_kb_simp)$name == i]
  
  team_kb = rbind(team_kb, data.frame(team = i, known_before = intra/choose(size,2), known_before_others = inte, size = size, max_components = max(components(g)$csize/size)))
}

Question on “strength_org_per_team”


#Seek Advice

g_sa = subgraph.edges(g_int_teams, eids = E(g_int_teams)[E(g_int_teams)$Question == "Who did you seek advice from last week?"], delete.vertices = FALSE)
E(g_sa)$weight = 1
g_sa_simp = simplify(g_sa, remove.loops = FALSE)

g_int_sa = subgraph.edges(g_int, eids = E(g_int)[E(g_int)$Question == "Who did you seek advice from last week?"], delete.vertices = FALSE)
E(g_int_sa)$weight = 1
g_int_sa_simp = simplify(g_int_sa, remove.loops = FALSE)

team_sa = data.frame()

for (i in V(g_sa_simp)$name)
{
  
  g = induced_subgraph(g_int_sa_simp, vids = V(g_int_sa_simp)[V(g_int_sa_simp)$new_name == i])
  
  intra = length(E(g_sa_simp)[get.edge.ids(g_sa_simp, vp = c(i, i))])
  org = length(E(g_sa_simp)[get.edge.ids(g_sa_simp, vp = c(i, "Organizing Team"))])
  inte = degree(g_sa_simp, v = i) - (2*intra) - org
  
  intra_wt = E(g_sa_simp)$weight[get.edge.ids(g_sa_simp, vp = c(i, i))]
  org_wt = E(g_sa_simp)$weight[get.edge.ids(g_sa_simp, vp = c(i, "Organizing Team"))]
  
  if(length(org_wt) == 0)
    org_wt = 0
  if(length(intra_wt) == 0)
    intra_wt = 0
  
  inte_wt = strength(g_sa_simp, v = i) - (2*intra_wt) - org_wt
  
  team_sa = rbind(team_sa, data.frame(team = i, density_intra_sa = igraph::edge_density(g), mean_strength_intra_sa = intra_wt/ecount(g), degree_inter_sa = inte, strength_org_per_person_sa = org_wt/vcount(g)))
}

#Work With

g_ww = subgraph.edges(g_int_teams, eids = E(g_int_teams)[E(g_int_teams)$Question == "Who did you work with last week?"], delete.vertices = FALSE)
E(g_ww)$weight = 1
g_ww_simp = simplify(g_ww, remove.loops = FALSE)

g_int_ww = subgraph.edges(g_int, eids = E(g_int)[E(g_int)$Question == "Who did you work with last week?"], delete.vertices = FALSE)
E(g_int_ww)$weight = 1
g_int_ww_simp = simplify(g_int_ww, remove.loops = FALSE)

team_ww = data.frame()

for (i in V(g_ww_simp)$name)
{
  
  g = induced_subgraph(g_int_ww_simp, vids = V(g_int_ww_simp)[V(g_int_ww_simp)$new_name == i])
  
  intra = length(E(g_ww_simp)[get.edge.ids(g_ww_simp, vp = c(i, i))])
  org = length(E(g_ww_simp)[get.edge.ids(g_ww_simp, vp = c(i, "Organizing Team"))])
  inte = degree(g_ww_simp, v = i) - (2*intra) - org
  
  intra_wt = E(g_ww_simp)$weight[get.edge.ids(g_ww_simp, vp = c(i, i))]
  org_wt = E(g_ww_simp)$weight[get.edge.ids(g_ww_simp, vp = c(i, "Organizing Team"))]
  
  if(length(org_wt) == 0)
    org_wt = 0
  if(length(intra_wt) == 0)
    intra_wt = 0
  
  inte_wt = strength(g_ww_simp, v = i) - (2*intra_wt) - org_wt
  
  team_ww = rbind(team_ww, data.frame(team = i, density_intra_ww = igraph::edge_density(g), mean_strength_intra_ww = intra_wt/ecount(g), degree_inter_ww = inte, strength_org_per_person_ww = org_wt/vcount(g)))
  
}

Network Properties


team_net_merged = data.frame()

kb_props = data.frame(team = V(g_kb_simp)$name, burt_kb = constraint(g_kb_simp, weights = E(g_kb_simp)$weight), closeness_kb = closeness(g_kb_simp, weights = 1/E(g_kb_simp)$weight, normalized = TRUE), betweenness_kb = betweenness(g_kb_simp, weights = 1/E(g_kb_simp)$weight, normalized = TRUE))
Warning in closeness(g_kb_simp, weights = 1/E(g_kb_simp)$weight, normalized = TRUE) :
  At centrality.c:2617 :closeness centrality is not well-defined for disconnected graphs
sa_props = data.frame(team = V(g_sa_simp)$name, burt_sa = constraint(g_sa_simp, weights = E(g_sa_simp)$weight), closeness_sa = closeness(g_sa_simp, weights = 1/E(g_sa_simp)$weight, normalized = TRUE), betweenness_sa = betweenness(g_sa_simp, weights = 1/E(g_sa_simp)$weight, normalized = TRUE))

ww_props = data.frame(team = V(g_ww_simp)$name, burt_ww = constraint(g_ww_simp, weights = E(g_ww_simp)$weight), closeness_ww = closeness(g_ww_simp, weights = 1/E(g_ww_simp)$weight, normalized = TRUE), betweenness_ww = betweenness(g_ww_simp, weights = 1/E(g_ww_simp)$weight, normalized = TRUE))
Warning in closeness(g_ww_simp, weights = 1/E(g_ww_simp)$weight, normalized = TRUE) :
  At centrality.c:2617 :closeness centrality is not well-defined for disconnected graphs
team_net_merged = merge(kb_props, sa_props, by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)
team_net_merged = merge(team_net_merged, ww_props, by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)
  1. Tasks Correlations and Regularity

tasks = merge(tasks, map[,c("Hash", "new_name")], by.x = "user_hash", by.y = "Hash", all.x = TRUE)
tasks$Team = tasks$new_name

a =  reshape2::acast(tasks, user_hash~tasks, length, drop = FALSE)
Using Team as value column: use value.var to override.
a[a>0] = 1 #Involved in an activity or not

b = reshape2::acast(tasks, new_name~tasks, length, drop = FALSE)
Using Team as value column: use value.var to override.
b[b>0] = 1

team_task_stats = data.frame()

for (i in unique(map$new_name))
{
  mem = map$Hash[map$new_name == i]
  ss = a[rownames(a) %in% mem,]
  
  sb = b[rownames(b) == i,]
  
  if(!is.null(nrow(ss)))
  {
     rs = rowSums(ss)/ncol(ss)
     cs = colSums(ss)/nrow(ss)
  }
  
  team_task_stats = rbind(team_task_stats, data.frame(team = i, mean_person_per_task = mean(cs), mean_task_per_person = mean(rs), team_activity_span = sum(sb)/length(sb)))
  
} 

tasks = tasks %>% select(-c("survey_id_no_exist", "new_name"))

write.csv(tasks, "../processed data/survey_tasks.csv")

Regularity


tasks = tasks %>% rowwise() %>% mutate(week = strsplit(survey_name, ":")[[1]][1])
tasks$week = factor(tasks$week, levels = c("Weekly 1", "Weekly 2", "Weekly 3", "Weekly 4"))

team_reg = data.frame()

for (i in unique(tasks$tasks))
{
  
  b = reshape2::acast(tasks[tasks$tasks == i, c("Team", "week")], Team~week, length, drop = FALSE)
  team_reg = rbind(team_reg, data.frame(team = rownames(b), task = i, no_weeks = apply(b, 1, function(x) sum(x>0)), gini = apply(b, 1, function(x) 1-ineq::Gini(x, corr = TRUE))))

}
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
Using week as value column: use value.var to override.
team_reg_avg = team_reg %>% group_by(team) %>% summarise(mean_nweeks_task = mean(no_weeks), mean_gini_task = mean(gini))

t = reshape2::acast(tasks, Team~week, length, drop = FALSE)
Using week as value column: use value.var to override.
team_reg_overall = data.frame(team = rownames(t), gini_overall_task = apply(t, 1, function(x) 1-ineq::Gini(x, corr = TRUE)))

team_reg_avg = merge(team_reg_avg, team_reg_overall, by.x = "team", by.y= "team", all.x = TRUE, all.y = TRUE)
  1. Slack Metrics

load("../../Evaluate/processed data/slack_all_int.RData")

df_total = df_total[df_total$timestamp <= as.numeric(as.POSIXct("2021-11-30", origin = "1970-01-01")),]
g_slack = graph_from_data_frame(df_total[,c(3,4,1,2,3)], directed = FALSE)
E(g_slack)$weight = 1
g_slack_simp = simplify(g_slack, remove.loops = FALSE)

vertices = read.csv("../../Evaluate/processed data/slack_id_verified.csv", stringsAsFactors = FALSE) %>% drop_na()
vertices$Team[vertices$Team == "Tool Owner"] = "Organizing Team"

g_slack_users = graph_from_data_frame(df_total, vertices = vertices[, c(3,2,4,5,6)], directed = FALSE)
E(g_slack_users)$weight = 1
g_slack_users_simp = simplify(g_slack_users, remove.loops = TRUE)

write.csv(df_total, "../processed data/slack_interactions.csv")

stats_slack = data.frame()

for (i in V(g_slack_simp)$name)
{
  if (!i %in% c("Organizing Team", "Tool Owner"))
  {
    
    g = induced_subgraph(g_slack_users_simp, vids = V(g_slack_users_simp)[V(g_slack_users_simp)$Team == i])
    
    intra = length(E(g_slack_simp)[get.edge.ids(g_slack_simp, vp = c(i, i))])
    org = length(E(g_slack_simp)[get.edge.ids(g_slack_simp, vp = c(i, "Organizing Team"))])
    inte = degree(g_slack_simp, v = i) - 2*intra - org
    
    intra_wt = E(g_slack_simp)$weight[get.edge.ids(g_slack_simp, vp = c(i, i))]
    org_wt = E(g_slack_simp)$weight[get.edge.ids(g_slack_simp, vp = c(i, "Organizing Team"))]
    
    if (length(intra_wt) == 0)
      intra_wt = 0
    if (length(org_wt) == 0)
      org_wt = 0
    
    inte_wt = strength(g_slack_simp, vids = i) - 2*intra_wt - org_wt
    
    ed = intra/ecount(g)
    if (is.nan(ed))
      ed = 0
    
    stats_slack = rbind(stats_slack, data.frame(team = i, density_intra_slack = edge_density(g), strength_intra_slack = intra_wt, mean_strength_intra_slack = ed, degree_inter_slack = inte, strength_inter_slack = inte_wt, strength_org_slack = org_wt))
  }
}

stats_slack = merge(stats_slack, reg_map, by.x = "team", by.y = "old_name", all.x = TRUE)

General Slack Props


texts = texts[texts$timestamp <= as.POSIXct("2021-11-30", origin = "1970-01-01"),]
t = texts %>% group_by(Team) %>% summarise(count_slack = n())

team_slack = data.frame(team = V(g_slack_simp)$name, burt_slack = constraint(g_slack_simp, weights = E(g_slack_simp)$weight), betweenness_slack = betweenness(g_slack_simp, weights = 1/E(g_slack_simp)$weight, normalized = TRUE), closeness_slack = closeness(g_slack_simp, weights = 1/E(g_slack_simp)$weight, normalized = TRUE))

team_slack = merge(team_slack, t, by.x = "team", by.y = "Team", all.x = TRUE, all.y = TRUE)
team_slack$count[is.na(team_slack$count)] = 0
team_slack = team_slack[!team_slack$team %in% c("Organizing Team", "Tool Owner"),]

team_slack = merge(team_slack, reg_map, by.x = "team", by.y = "old_name", all.x = TRUE)

write.csv(texts, "../processed data/slack_messages.csv")
  1. Diversity Metrics

shannon = function(list)
{
  ent = 0
  for (i in unique(list))
  {
    t = sum(list == i)
    n = length(list)
    ent = ent + (t/n)*log(t/n)
  }
  
  return(-1*ent)
}

reg$age = floor(as.numeric(difftime(as.Date("2022-04-01"), as.Date(reg$birthday, tryFormats = c("%m/%d/%Y")), unit="weeks"))/52.25)
metrics = data.frame(Team = unique(reg$new_name))

for (i in c("gender", "country_orig", "country_resid", "education", "communication", "exante_project_SDG", "background", "occupation"))
{
  temp = reg[,c("new_name", i)]
  temp = clean_split_mcq(temp)
  colnames(temp) = c("Team", "var")
  

  t = temp %>% group_by(Team) %>% summarise(shannon = shannon(var), span = length(unique(var)))
  colnames(t) = c("Team", paste(i, "_shannon", sep = ''), paste(i, "_span", sep = ''))
  
  metrics = merge(metrics, t, by.x = "Team", by.y = "Team", all.x = TRUE, all.y = TRUE)
  
}

metrics = merge(metrics, teams, by.x = "Team", by.y = "Team Name", all.x = TRUE)

reg$education_code = 0
reg$education_code[reg$education == "Highschool"] = 1
reg$education_code[reg$education == "University (Undergraduate / Bachelors)"] = 2
reg$education_code[reg$education == "University (Graduate / Masters)"] = 3


age = reg[,c("new_name", "age", "exante_project", "education_code")] %>% group_by(new_name) %>% summarise(mean_age = mean(age), mean_exante = sum(exante_project == "Yes")/length(exante_project), age_gap = max(age) - min(age), mean_education = mean(education_code))

metrics = merge(metrics, age, by.x = "Team", by.y = "new_name", all.x = TRUE, all.y = TRUE)
metrics$team = metrics$Team


metrics = metrics %>% select(-c("Team", "Stage", "Type"))

Correlations


x = colnames(outcome)
x = x[!x %in% c("Team", "Stage", "Type")]

outcome$`Data Collection and NSO`[is.na(outcome$`Data Collection and NSO`)] = 0

temp_outcome = outcome
LoS = 0.1

Function for computing the correlation matrix


corr_matrix = function(matrix, colnames1, colnames2)
{
  df_corr = data.frame()
  
  for (i in colnames1)
  {
    for (j in colnames2)
    {
      c = cor.test(matrix[,j], matrix[,i])
      df_corr = rbind(df_corr, data.frame(i = i, j = j, cor = c$estimate, p_val = c$p.value))
    }
  }
  
  return(df_corr)
}


eval_randomized = function(col1, col2, n = 1000)
{
  df_rand = data.frame()
  
  for (i in 1:n)
  {
    c = cor.test(sample(col1), col2)
    df_rand = rbind(df_rand, data.frame(iteration = i, p_val = c$p.value, cor = c$estimate))
  }
  
  #return(sum(df_rand$p_val <= LoS)/n)
  return(df_rand$cor)
  
}


df_list = list("known_before" = team_kb, "seek_advice" = team_sa, "work_with" = team_ww, "merged_network" = team_net_merged, "merged_slack" = team_slack, "slack_statistics" = stats_slack, "team_task_stats" = team_task_stats, "task_regularity" = team_reg_avg, "diversity_metrics" = metrics)

df_sig = data.frame()

for (i in 1:length(df_list))
{
  pdf(paste("../figures/correlations/", names(df_list)[i], "_outcome.pdf", sep = ""), height = 10, width = 12)
  
  temp_outcome$Team = sample(temp_outcome$Team)
  
  df = df_list[[i]]
  y = colnames(df)
  
  if ("new_name" %in% y)
    df$team = df$new_name
  
  temp = merge(df[!df$team %in% c("Organizing Team", "C5: Ashifa Nazrin"),], outcome, by.x = "team", by.y = "Team", all.x = TRUE, all.y = TRUE)
  temp_rand = merge(df[!df$team %in% c("Organizing Team", "C5: Ashifa Nazrin"),], temp_outcome, by.x = "team", by.y = "Team", all.x = TRUE, all.y = TRUE)
  
  df_corr = corr_matrix(temp, x, y[!y %in% c("team", "new_name")])
  df_corr_rand = corr_matrix(temp_rand, x, y[!y %in% c("team", "new_name")])
  
  df_corr$cor[df_corr$p_val > LoS] = 0
  df_corr$cor = round(df_corr$cor, 3)

  df_corr_rand$cor[df_corr_rand$p_val > LoS] = 0
  df_corr_rand$cor = round(df_corr_rand$cor, 3)
  
  plt = ggplot(df_corr) + geom_tile(aes(x = j, y = i, fill = cor), lwd = 1.5, linetype = 1) + scale_fill_gradient2(low = "blue", high = "red") + theme_bw(base_size = 15) +    
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank()) + ylab("") + xlab("") + geom_text(aes(x = j, y = i, label = cor)) +
  ggtitle(paste(names(df_list)[i], " vs Outcome", sep = ""))
  
  if (length(y) > 5)
    plt = plt + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.text.x = element_text(angle = 90))
  
  #ggsave(plt, filename = paste("../figures/correlations/", names(df_list)[i], "_outcome.png", sep = ""), width = 12, height = 7)
  print(plt)
  
  plt = ggplot(df_corr_rand) + geom_tile(aes(x = j, y = i, fill = cor), lwd = 1.5, linetype = 1) + scale_fill_gradient2(low = "blue", high = "red") + theme_bw(base_size = 15) +    
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank()) + ylab("") + xlab("") + geom_text(aes(x = j, y = i, label = cor)) +
  ggtitle(paste(names(df_list)[i], " vs Outcome Rand", sep = ""))
  
  if (length(y) > 5)
    plt = plt + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.text.x = element_text(angle = 90))
  
  #ggsave(plt, filename = paste("../figures/rand_correlations/", names(df_list)[i], "_outcome_rand.png", sep = ""), width = 12, height = 7)
  print(plt)
  
  dev.off()
  
  df_sig = rbind(df_sig, df_corr[df_corr$p_val <= LoS, c("i","j")])
  
}
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning in cor(x, y) : the standard deviation is zero
Warning: Removed 15 rows containing missing values (geom_text).
Warning: Removed 15 rows containing missing values (geom_text).
df_sig = df_sig %>% drop_na()

Linear Model

kb = team_kb[, c("team", "max_components")]
sa = team_sa[, c("degree_inter_sa", "density_intra_sa", "team")]
#colnames(sa) = c("degree_inter_sa", "density_intra_sa", "team")
ww = team_ww[, c("mean_strength_intra_ww", "team")]
#colnames(ww) = c("mean_strength_intra_ww", "team")

ts = team_slack[, c("new_name", "burt_slack", "closeness_slack", "count_slack")]
colnames(ts) = c("team", "burt_slack", "closeness_slack", "no_messages_slack")
ss = stats_slack[, c("new_name", "strength_intra_slack", "degree_inter_slack", "strength_inter_slack", "strength_org_slack")]
colnames(ss) = c("team", "strength_intra_slack", "degree_inter_slack", "strength_inter_slack", "strength_org_slack")

tra = team_reg_avg[, c("team", "mean_nweeks_task", "mean_gini_task", "gini_overall_task")]
#colnames(tra) = c("team", "mean_nweeks_task", "mean_gini_task", "gini_overall_task")

temp = sa
temp = merge(temp, kb, by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)
temp = merge(temp, ww, by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)
temp = merge(temp, team_net_merged[, c("team", "burt_sa", "closeness_sa")], by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)
temp = merge(temp, ts, by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)
temp = merge(temp, ss, by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)
temp = merge(temp, team_task_stats[,c("mean_task_per_person", "team", "team_activity_span")], by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)
temp = merge(temp, tra, by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)
temp = merge(temp, metrics[, c("gender_shannon", "education_shannon", "team", "background_span", "size", "mean_age", "mean_exante", "age_gap", "mean_education")], by.x = "team", by.y = "team", all.x = TRUE, all.y = TRUE)

temp = temp[!temp$team %in% c("Organizing Team", "C5: Ashifa Nazrin", NA),]
#temp = merge(temp, outcome[,c("Team", "formation")], by.x = "team", by.y = "Team", all.x = TRUE, all.y = TRUE)

df_key_attributes = temp

Linear Models for different outcome variables

for (i in c("Total", "Weekly Evaluation", "Commitment" , "Attendance", "Deliverables", "Final Pitch", "mean_novelty", "mean_relevance", "mean_feasibility", "mean_crowdsourcing", "mean_presentation"))
{
  mod_temp = merge(temp, outcome[,c(i, "Team")], by.x = "team", by.y = "Team", all.x = TRUE, all.y = TRUE)
  v = df_sig[df_sig$i == i,]
  
  list = as.character(v$j)
  list = list[list %in% colnames(temp)]
  
  formula = paste(paste(i, " ~ ", sep = ""), gsub(",", "+", (toString(list))), sep = "")
  
  mod = lm(data = mod_temp[,c(i, list)], formula = as.formula(formula))
  
}

mod_total = merge(temp, outcome[,c("Total", "formation", "stage_progressed","Team")], by.x = "team", by.y = "Team", all.x = TRUE, all.y = TRUE)

mod = lm(data = mod_total, formula = Total ~ mean_strength_intra_ww + burt_sa +  closeness_slack + gini_overall_task + strength_inter_slack + strength_org_slack)

plot_model(mod, type = "std2", sort.est = TRUE, vline.color = "grey80", show.values = TRUE, value.offset = 0.3, title = "") + theme_bw(base_size = 15)

NA
NA

mod = lm(data = mod_total, formula = Total ~ mean_age + age_gap)

plot_model(mod, type = "std2", sort.est = TRUE, vline.color = "grey80", show.values = TRUE, value.offset = 0.3, title = "") + theme_bw(base_size = 15)


mod = lm(data = mod_total, formula = formation ~ mean_age + age_gap)

plot_model(mod, type = "std2", sort.est = TRUE, vline.color = "grey80", show.values = TRUE, value.offset = 0.3, title = "formation") + theme_bw(base_size = 15)


mod = lm(data = mod_total, formula = stage_progressed ~ mean_age + age_gap)

plot_model(mod, type = "std2", sort.est = TRUE, vline.color = "grey80", show.values = TRUE, value.offset = 0.3, title = "stage_progressed") + theme_bw(base_size = 15)

NA
NA

l = x[!x %in% c("mean_presentation")]

cd = corr_matrix(outcome, l, l)

cd$cor[cd$p_val > 0.05] = 0
cd$cor = round(cd$cor, 3)

plt = ggplot(cd) + geom_tile(aes(x = j, y = i, fill = cor), lwd = 1.5, linetype = 1) + scale_fill_gradient2(low = "blue", high = "red") + theme_bw(base_size = 15) + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank()) + ylab("") + xlab("") + geom_text(aes(x = j, y = i, label = cor)) + ggtitle("Multicollinearity Check") + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.text.x = element_text(angle = 90))

ggplotly(plt)
NA

t = df_key_attributes[, c("team", "size", "age_gap", "background_span", "mean_education","mean_exante", "no_messages_slack", "strength_org_slack", "closeness_slack", "max_components", "mean_strength_intra_ww", "burt_sa", "degree_inter_sa", "team_activity_span", "gini_overall_task", "mean_task_per_person")]

colnames(t) = c("team", "team_size", "age_gap", "background_span", "mean_education_level", "prior_sdg_experience", "activity_slack", "strength_org_slack", "closeness_slack", "fraction_component_known_before", "collaborations_intra_team", "burt_seek_advice", "degree_inter_seek_dvice", "team_activity_span", "activity_regularity", "mean_task_per_person")

write.csv(t, "../processed data/correlation features.csv")

t_t = merge(t, outcome, by.x = "team", by.y = "Team", all.x = TRUE, all.y = TRUE)
y = colnames(t)

df_corr = corr_matrix(t_t, x[!x %in% c("formation")], c(y[!y %in% c("team", "new_name")]))

df_corr$cor[df_corr$p_val > LoS] = NA
df_corr$cor = round(df_corr$cor, 3)

plt = ggplot(df_corr) + geom_tile(aes(x = j, y = i, fill = cor), lwd = 1.5, linetype = 1) + scale_fill_gradient2(low = "blue", high = "red", na.value = "grey90") + theme_bw(base_size = 15) + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank()) + ylab("") + xlab("") + geom_text(aes(x = j, y = i, label = cor)) + ggtitle("Correlations") + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.text.x = element_text(angle = 90, hjust = 0.95, vjust = 0.2))

ggplotly(plt)

ggsave(plt, filename = "../figures/correlations/siginificant_correlations.png", width = 10, height = 7)
Warning: Removed 177 rows containing missing values (geom_text).

Pre-Formed vs Algorithm


t = merge(df_key_attributes, outcome, by.x = "team", by.y = "Team", all.x = TRUE, all.y = TRUE)
#t = outcome
df_type = data.frame()

for (j in colnames(t))
{
  if (! j %in% c("team", "Type", "new_name", "Stage", "formation", "Team"))
  {
    df = t[,c("Type", j)]
    w = wilcox.test(df[df$Type == "Pre-formed",j], df[df$Type == "Algorithm",j], alternative = "two.sided")
    stat = mean(df[df$Type == "Pre-formed",j], na.rm = TRUE) > mean(df[df$Type == "Algorithm",j], na.rm = TRUE)
    df_type = rbind(df_type, data.frame(attribute = j, p_value = w$p.value, key = if (stat) "Pre-Formed" else "Algorithm"))
  }
}

df_type$key[df_type$p_value > 0.1] = NA

plt = ggplot(df_type, aes(y = reorder(attribute, p_value), x = p_value)) + geom_bar(stat = "identity", aes(fill = key)) + theme_bw(base_size = 15) + xlab("P Value") + ylab("") + geom_vline(xintercept = 0.1, linetype = 2, color = "red")

ggplotly(plt)

ggsave(plt, filename = "../figures/team_type.png", height = 10, width = 7)

write.csv(outcome, "../processed data/composite_outcome.csv")
#write.csv(reg, "../processed data/reg_edited.csv")

temp = unnest(reg, cols = c("communication"))
temp = temp %>% select(-"birthday")
write.csv(temp, file = "../processed data/reg_edited.csv")
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKMC4gTG9hZCBEYXRhCgpgYGB7cn0KCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHNqUGxvdCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBsb3RseSkKCnNvdXJjZSgiLi4vLi4vQWNjZWxlcmF0ZS9ub3RlYm9va3MvY3VzdG9tX2Z1bmN0aW9ucy5SIikKCnRlYW1zID0gcmVhZF9leGNlbCgiLi4vZGF0YS9PMTdDbGltYXRlR2VuZGVyX3RlYW1mb3JtYXRpb24ueGxzeCIpCiN0ZWFtcyA9IGxhcHBseSh0ZWFtcywgYXMuY2hhcmFjdGVyKQoKYXNzZXNtZW50ID0gcmVhZF9leGNlbCgiLi4vZGF0YS9PMTdDbGltYXRlR2VuZGVyX2Fzc2Vzc21lbnQueGxzeCIpCgpsb2FkKCIuLi8uLi9BY2NlbGVyYXRlL3Byb2Nlc3NlZCBkYXRhL3JlZ2lzdHJhdGlvbi5SRGF0YSIpCgptYXAgPSByZWFkLmNzdigiLi4vLi4vQWNjZWxlcmF0ZS9kYXRhL3RlYW1fdXNlcnNfaGFzaGVkLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKY29sbmFtZXMobWFwKSA9IGMoIlRlYW0iLCAiSUQiLCAiSGFzaCIsICJNZW50b3JzIikKCnJlZyA9IG1lcmdlKHJlZywgbWFwWyxjKCJUZWFtIiwgIkhhc2giKV0sIGJ5LnggPSAiSUQiLCBieS55ID0gIkhhc2giKQoKcmVnX21hcCA9IGMoIkEyOiBXb21lbiAmIFRlY2hub2xvZ3kgQWdhaW5zdCBDbGltYXRlIENoYW5nZSIgPSAiVDY6IFdvbWVuICYgVGVjaG5vbG9neSBBZ2FpbnN0IENsaW1hdGUgQ2hhbmdlIiwgIkIyOiBURUFNIEZPSUxFRCIgPSAiVDM6IFRFQU0gRk9JTEVEIiwgIkMxOiBBbmRhcMOpIEluc3RpdHV0ZSIgPSAiVDEzOiBBbmRhcMOpIEluc3RpdHV0ZSIsICJDMzogV09NRVIiID0gIlQ1OiBXT01FUiIsICJBNTogRG9uYXRlIFdhdGVyIFByb2plY3QiID0gIlQ5OiBEb25hdGVXYXRlciIsICJCNTogUmlnaHRzIG9mIENsaW1hdGUiID0gIlQxMTogUmlnaHRzIG9mIENsaW1hdGUiLCAiQjM6IEVjbyBXaW5uZXJzIiA9ICJUMTQ6IEVjbyBXaW5uZXJzIiwgIkI0OiBXb21lbiA0IFN1c3RhaW5hYmxlIFdvcmxkIiA9ICJUMTI6IFdvbWVuIDQgU3VzdGFpbmFibGUgV29ybGQiLCAiQTE6IFVwIEdldCBBcHAvQ2l0aUNFUk4iID0gIlQ3OiBVcEdldCBhcHAgLSBDaXRpQ0VSTiBQcm9qZWN0IiwgIkIxOiBXYXRlciBXYXJyaW9ycyIgPSAiVDEwOiBXYXRlciBXYXJyaW9ycyIsICJDMjogUEFNIiA9ICJUNDogUEFNIiwgIkM0OiBDbGltYXRlIEdlbmRlciBKdXN0aWNlIiA9ICJUODogQ2xpbWF0ZSBHZW5kZXIgSnVzdGljZSIsICJBMzogUmh5dGhtIG9mIEJhbWJvb3MiID0gIlQxOiBTRGVzaUduIChPbGQgbmFtZTogUmh5dGhtIG9mIEJhbWJvb3MpIiwgIkM1OiBBc2hpZmEgTmF6cmluIiA9ICJDNTogQXNoaWZhIE5henJpbiIsICJBNDogRmxvb2QgUmFuZ2VycyIgPSAiVDI6IEZsb29kIFJhbmdlcnMiKQoKcmVnX21hcCA9IGRhdGEuZnJhbWUob2xkX25hbWUgPSBuYW1lcyhyZWdfbWFwKSwgbmV3X25hbWUgPSByZWdfbWFwKQpyZWcgPSBtZXJnZShyZWcsIHJlZ19tYXAsIGJ5LnggPSAiVGVhbSIsIGJ5LnkgPSAib2xkX25hbWUiLCBhbGwueCA9IFRSVUUpCgp3cml0ZS5jc3YodW5uZXN0KHJlZywgY29scyA9IGMoImNvbW11bmljYXRpb24iKSksIGZpbGUgPSAiLi4vcHJvY2Vzc2VkIGRhdGEvcmVnX2VkaXRlZC5jc3YiKQoKbWFwID0gbWVyZ2UobWFwLCByZWdfbWFwLCBieS54ID0gIlRlYW0iLCBieS55ID0gIm9sZF9uYW1lIiwgYWxsLnggPSBUUlVFKQptYXAkbmV3X25hbWUgPSBhcy5jaGFyYWN0ZXIobWFwJG5ld19uYW1lKQptYXAkbmV3X25hbWVbbWFwJFRlYW0gPT0gIk9yZ2FuaXppbmcgVGVhbSJdID0gIk9yZ2FuaXppbmcgVGVhbSIKCnNpemUgPSBtYXAgJT4lIGdyb3VwX2J5KG5ld19uYW1lKSAlPiUgc3VtbWFyaXNlKHNpemUgPSBuKCkpCgpqdXJ5X3Njb3JlcyA9IHJlYWQuY3N2KCIuLi9kYXRhL2Fzc2Vzc21lbnRfc2hlZXQxLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCmp1cnlfc2NvcmVzX2F2ZyA9IGp1cnlfc2NvcmVzICU+JSBncm91cF9ieShDaG9vc2UudGhlLlRlYW0pICU+JSBzdW1tYXJpc2UobWVhbl9ub3ZlbHR5ID0gbWVhbihOb3ZlbHR5Li5Jcy50aGUucGl0Y2guYmFzZWQub24uYS5uZXcuaWRlYS5vci5jb25jZXB0Lm9yLnVzaW5nLmV4aXN0aW5nLmNvbmNlcHRzLmluLmEubmV3LmNvbnRleHQuLCBuYS5ybSA9IFRSVUUpLCBtZWFuX3JlbGV2YW5jZSA9IG1lYW4oUmVsZXZhbmNlLi5Jcy50aGUuc29sdXRpb24ucHJvcG9zZWQucmVsZXZhbnQudG8udGhlLmNoYWxsZW5nZS5vci5wb3RlbnRpYWxseS5pbXBhY3RmdWwuLiwgbmEucm0gPSBUUlVFKSwgbWVhbl9mZWFzaWJpbGl0eSA9IG1lYW4oRmVhc2liaWxpdHkuLklzLnRoZS5wcm9qZWN0LmltcGxlbWVudGFibGUud2l0aC5yZWFzb25hYmxlLnRpbWUuYW5kLmVmZm9ydC5mcm9tLnRoZS50ZWFtLiwgbmEucm0gPSBUUlVFKSwgbWVhbl9jcm93ZHNvdXJjaW5nID0gbWVhbihDcm93ZHNvdXJjaW5nLi5Jcy50aGVyZS5hbi5lZmZlY3RpdmUuY3Jvd2Rzb3VyY2luZy5jb21wb25lbnQuLCBuYS5ybSA9IFRSVUUpLCBtZWFuX3ByZXNlbnRhdGlvbiA9IG1lYW4oSG93LndvdWxkLnlvdS5yYXRlLnRoaXMudGVhbS5zLm92ZXJhbGwucHJlc2VudGF0aW9uLnNraWxscy5kdXJpbmcudGhpcy5waXRjaC4sIG5hLnJtID0gVFJVRSkpCgpqdXJ5X3Njb3Jlc19hdmcgPSBqdXJ5X3Njb3Jlc19hdmdbLWMoMSksXQoKYGBgCgpPdXRjb21lIFZhcmlhYmxlCgoKYGBge3J9CgpvdXRjb21lID0gYXNzZXNtZW50WyxjKCJUZWFtIiwgIlRvdGFsIiwgIldlZWtseSBFdmFsdWF0aW9uIiwgIkNvbW1pdG1lbnQiLCAiQXR0ZW5kYW5jZSIsICJEZWxpdmVyYWJsZXMiLCAiRmluYWwgUGl0Y2giLCAiRGF0YSBDb2xsZWN0aW9uIGFuZCBOU08iLCAiQXBwcm9wcmlhdGVuZXNzIG9mIE1ldGhvZG9sb2d5IildCm91dGNvbWUgPSBtZXJnZShvdXRjb21lLCB0ZWFtc1ssYygiVGVhbSBOYW1lIiwgIlN0YWdlIiwgIlR5cGUiKV0sIGJ5LnggPSAiVGVhbSIsIGJ5LnkgPSAiVGVhbSBOYW1lIiwgYWxsLnggPSBUUlVFKQpvdXRjb21lJFN0YWdlID0gZmFjdG9yKG91dGNvbWUkU3RhZ2UsIGxldmVscyA9IGMoIkV2YWx1YXRlIiwgIkFjY2VsZXJhdGUiLCAiUmVmaW5lIiksIG9yZGVyZWQgPSBUUlVFKQoKb3V0Y29tZSA9IG1lcmdlKG91dGNvbWUsIGp1cnlfc2NvcmVzX2F2ZywgYnkueCA9ICJUZWFtIiwgYnkueSA9ICJDaG9vc2UudGhlLlRlYW0iLCBhbGwueCA9IFRSVUUsIGFsbC55ID0gVFJVRSkKb3V0Y29tZSRzdGFnZV9wcm9ncmVzc2VkID0gMApvdXRjb21lJHN0YWdlX3Byb2dyZXNzZWRbb3V0Y29tZSRTdGFnZSA9PSAiQWNjZWxlcmF0ZSJdID0gMQpvdXRjb21lJHN0YWdlX3Byb2dyZXNzZWRbb3V0Y29tZSRTdGFnZSA9PSAiUmVmaW5lIl0gPSAyCgpvdXRjb21lJGZvcm1hdGlvbiA9IDAKb3V0Y29tZSRmb3JtYXRpb25bb3V0Y29tZSRUeXBlID09ICJBbGdvcml0aG0iXSA9IDEKCmBgYAoKClN1cnZleXMgYW5kIEludGVyYWN0aW9ucwoKYGBge3J9Cgpsb2FkKCIuLi8uLi9FdmFsdWF0ZS9wcm9jZXNzZWQgZGF0YS9zdXJ2ZXlzLlJEYXRhIikKCmludGVyID0gaW50ZXJhY3Rpb25zWyxjKDEsOCwyLDMpXQppbnRlciA9IG1lcmdlKGludGVyLCBtYXBbLGMoIklEIiwgIm5ld19uYW1lIildLCBieS54ID0gInVzZXJfaWQiLCBieS55ID0gIklEIiwgYWxsLnggPSBUUlVFKQpjb2xuYW1lcyhpbnRlcikgPSBjKCJGcm9tIiwgIlRvIiwgIlN1cnZleV9pZCIsICJRdWVzdGlvbiIsICJGcm9tX3RlYW0iKQppbnRlciA9IG1lcmdlKGludGVyLCBtYXBbLGMoIklEIiwgIm5ld19uYW1lIildLCBieS54ID0gIlRvIiwgYnkueSA9ICJJRCIsIGFsbC54ID0gVFJVRSkKY29sbmFtZXMoaW50ZXIpW2NvbG5hbWVzKGludGVyKSA9PSAibmV3X25hbWUiXSA9ICJUb190ZWFtIgoKaW50ZXIgPSBpbnRlclshaW50ZXIkVG8gJWluJSBjKDM0KSwgYygyLDEsMyw0LDUsNildCgp0ZWFtcyA9IG1lcmdlKHRlYW1zLCBzaXplLCBieS54ID0gIlRlYW0gTmFtZSIsIGJ5LnkgPSAibmV3X25hbWUiLCBhbGwueCA9IFRSVUUpCgpnX2ludCA9IGdyYXBoX2Zyb21fZGF0YV9mcmFtZShpbnRlciwgZGlyZWN0ZWQgPSBGQUxTRSwgdmVydGljZXMgPSBtYXBbLGMoMiwxLDMsNCw1KV0pCgpnX2ludF90ZWFtcyA9IGdyYXBoX2Zyb21fZGF0YV9mcmFtZShpbnRlclssYyg1LDYsMTo0KV0sIGRpcmVjdGVkID0gRkFMU0UsIHZlcnRpY2VzID0gdGVhbXMpCkUoZ19pbnRfdGVhbXMpJHdlaWdodCA9IDEKZ19pbnRfdGVhbXNfc2ltcCA9IHNpbXBsaWZ5KGdfaW50X3RlYW1zLCByZW1vdmUubG9vcHMgPSBGQUxTRSkKCndyaXRlLmNzdihpbnRlciwgIi4uL3Byb2Nlc3NlZCBkYXRhL3N1cnZleV9pbnRlcmFjdGlvbnMuY3N2IikKCmBgYAoKCioqKioqKioqKioqKioqKioqKioqKioqCgoxLiBTdXJ2ZXkgTWV0cmljcwoKYSkgSW50ZXJhY3Rpb25zCgpgYGB7cn0KCiNLbm93biBCZWZvcmUKCmdfa2IgPSBzdWJncmFwaC5lZGdlcyhnX2ludF90ZWFtcywgZWlkcyA9IEUoZ19pbnRfdGVhbXMpW0UoZ19pbnRfdGVhbXMpJFF1ZXN0aW9uID09ICJXaGljaCBvZiB0aGVzZSBwZW9wbGUgZGlkIHlvdSBrbm93IHBlcnNvbmFsbHkgYmVmb3JlPyJdLCBkZWxldGUudmVydGljZXMgPSBGQUxTRSkKRShnX2tiKSR3ZWlnaHQgPSAxCmdfa2Jfc2ltcCA9IHNpbXBsaWZ5KGdfa2IsIHJlbW92ZS5sb29wcyA9IEZBTFNFKQoKZ19rYl91c2VycyA9IHN1YmdyYXBoLmVkZ2VzKGdfaW50LCBlaWRzID0gRShnX2ludClbRShnX2ludCkkUXVlc3Rpb24gPT0gIldoaWNoIG9mIHRoZXNlIHBlb3BsZSBkaWQgeW91IGtub3cgcGVyc29uYWxseSBiZWZvcmU/Il0sIGRlbGV0ZS52ZXJ0aWNlcyA9IEZBTFNFKQoKdGVhbV9rYiA9IGRhdGEuZnJhbWUoKQoKZm9yIChpIGluIFYoZ19rYl9zaW1wKSRuYW1lKQp7CiAgZyA9IGluZHVjZWRfc3ViZ3JhcGgoZ19rYl91c2VycywgdmlkcyA9IFYoZ19rYl91c2VycylbVihnX2tiX3VzZXJzKSRuZXdfbmFtZSA9PSBpXSkKICAKICBpbnRyYSA9IGxlbmd0aChFKGdfa2Jfc2ltcClbZ2V0LmVkZ2UuaWRzKGdfa2Jfc2ltcCwgdnAgPSBjKGksIGkpKV0pCiAgb3JnID0gbGVuZ3RoKEUoZ19rYl9zaW1wKVtnZXQuZWRnZS5pZHMoZ19rYl9zaW1wLCB2cCA9IGMoaSwgIk9yZ2FuaXppbmcgVGVhbSIpKV0pCiAgaW50ZSA9IGRlZ3JlZShnX2tiX3NpbXAsIHYgPSBpKSAtICgyKmludHJhKSAtIG9yZwogIHNpemUgPSBWKGdfa2Jfc2ltcCkkc2l6ZVtWKGdfa2Jfc2ltcCkkbmFtZSA9PSBpXQogIAogIHRlYW1fa2IgPSByYmluZCh0ZWFtX2tiLCBkYXRhLmZyYW1lKHRlYW0gPSBpLCBrbm93bl9iZWZvcmUgPSBpbnRyYS9jaG9vc2Uoc2l6ZSwyKSwga25vd25fYmVmb3JlX290aGVycyA9IGludGUsIHNpemUgPSBzaXplLCBtYXhfY29tcG9uZW50cyA9IG1heChjb21wb25lbnRzKGcpJGNzaXplL3NpemUpKSkKfQoKCmBgYAoKClF1ZXN0aW9uIG9uICJzdHJlbmd0aF9vcmdfcGVyX3RlYW0iCgpgYGB7cn0KCiNTZWVrIEFkdmljZQoKZ19zYSA9IHN1YmdyYXBoLmVkZ2VzKGdfaW50X3RlYW1zLCBlaWRzID0gRShnX2ludF90ZWFtcylbRShnX2ludF90ZWFtcykkUXVlc3Rpb24gPT0gIldobyBkaWQgeW91IHNlZWsgYWR2aWNlIGZyb20gbGFzdCB3ZWVrPyJdLCBkZWxldGUudmVydGljZXMgPSBGQUxTRSkKRShnX3NhKSR3ZWlnaHQgPSAxCmdfc2Ffc2ltcCA9IHNpbXBsaWZ5KGdfc2EsIHJlbW92ZS5sb29wcyA9IEZBTFNFKQoKZ19pbnRfc2EgPSBzdWJncmFwaC5lZGdlcyhnX2ludCwgZWlkcyA9IEUoZ19pbnQpW0UoZ19pbnQpJFF1ZXN0aW9uID09ICJXaG8gZGlkIHlvdSBzZWVrIGFkdmljZSBmcm9tIGxhc3Qgd2Vlaz8iXSwgZGVsZXRlLnZlcnRpY2VzID0gRkFMU0UpCkUoZ19pbnRfc2EpJHdlaWdodCA9IDEKZ19pbnRfc2Ffc2ltcCA9IHNpbXBsaWZ5KGdfaW50X3NhLCByZW1vdmUubG9vcHMgPSBGQUxTRSkKCnRlYW1fc2EgPSBkYXRhLmZyYW1lKCkKCmZvciAoaSBpbiBWKGdfc2Ffc2ltcCkkbmFtZSkKewogIAogIGcgPSBpbmR1Y2VkX3N1YmdyYXBoKGdfaW50X3NhX3NpbXAsIHZpZHMgPSBWKGdfaW50X3NhX3NpbXApW1YoZ19pbnRfc2Ffc2ltcCkkbmV3X25hbWUgPT0gaV0pCiAgCiAgaW50cmEgPSBsZW5ndGgoRShnX3NhX3NpbXApW2dldC5lZGdlLmlkcyhnX3NhX3NpbXAsIHZwID0gYyhpLCBpKSldKQogIG9yZyA9IGxlbmd0aChFKGdfc2Ffc2ltcClbZ2V0LmVkZ2UuaWRzKGdfc2Ffc2ltcCwgdnAgPSBjKGksICJPcmdhbml6aW5nIFRlYW0iKSldKQogIGludGUgPSBkZWdyZWUoZ19zYV9zaW1wLCB2ID0gaSkgLSAoMippbnRyYSkgLSBvcmcKICAKICBpbnRyYV93dCA9IEUoZ19zYV9zaW1wKSR3ZWlnaHRbZ2V0LmVkZ2UuaWRzKGdfc2Ffc2ltcCwgdnAgPSBjKGksIGkpKV0KICBvcmdfd3QgPSBFKGdfc2Ffc2ltcCkkd2VpZ2h0W2dldC5lZGdlLmlkcyhnX3NhX3NpbXAsIHZwID0gYyhpLCAiT3JnYW5pemluZyBUZWFtIikpXQogIAogIGlmKGxlbmd0aChvcmdfd3QpID09IDApCiAgICBvcmdfd3QgPSAwCiAgaWYobGVuZ3RoKGludHJhX3d0KSA9PSAwKQogICAgaW50cmFfd3QgPSAwCiAgCiAgaW50ZV93dCA9IHN0cmVuZ3RoKGdfc2Ffc2ltcCwgdiA9IGkpIC0gKDIqaW50cmFfd3QpIC0gb3JnX3d0CiAgCiAgdGVhbV9zYSA9IHJiaW5kKHRlYW1fc2EsIGRhdGEuZnJhbWUodGVhbSA9IGksIGRlbnNpdHlfaW50cmFfc2EgPSBpZ3JhcGg6OmVkZ2VfZGVuc2l0eShnKSwgbWVhbl9zdHJlbmd0aF9pbnRyYV9zYSA9IGludHJhX3d0L2Vjb3VudChnKSwgZGVncmVlX2ludGVyX3NhID0gaW50ZSwgc3RyZW5ndGhfb3JnX3Blcl9wZXJzb25fc2EgPSBvcmdfd3QvdmNvdW50KGcpKSkKfQoKYGBgCgpgYGB7cn0KCiNXb3JrIFdpdGgKCmdfd3cgPSBzdWJncmFwaC5lZGdlcyhnX2ludF90ZWFtcywgZWlkcyA9IEUoZ19pbnRfdGVhbXMpW0UoZ19pbnRfdGVhbXMpJFF1ZXN0aW9uID09ICJXaG8gZGlkIHlvdSB3b3JrIHdpdGggbGFzdCB3ZWVrPyJdLCBkZWxldGUudmVydGljZXMgPSBGQUxTRSkKRShnX3d3KSR3ZWlnaHQgPSAxCmdfd3dfc2ltcCA9IHNpbXBsaWZ5KGdfd3csIHJlbW92ZS5sb29wcyA9IEZBTFNFKQoKZ19pbnRfd3cgPSBzdWJncmFwaC5lZGdlcyhnX2ludCwgZWlkcyA9IEUoZ19pbnQpW0UoZ19pbnQpJFF1ZXN0aW9uID09ICJXaG8gZGlkIHlvdSB3b3JrIHdpdGggbGFzdCB3ZWVrPyJdLCBkZWxldGUudmVydGljZXMgPSBGQUxTRSkKRShnX2ludF93dykkd2VpZ2h0ID0gMQpnX2ludF93d19zaW1wID0gc2ltcGxpZnkoZ19pbnRfd3csIHJlbW92ZS5sb29wcyA9IEZBTFNFKQoKdGVhbV93dyA9IGRhdGEuZnJhbWUoKQoKZm9yIChpIGluIFYoZ193d19zaW1wKSRuYW1lKQp7CiAgCiAgZyA9IGluZHVjZWRfc3ViZ3JhcGgoZ19pbnRfd3dfc2ltcCwgdmlkcyA9IFYoZ19pbnRfd3dfc2ltcClbVihnX2ludF93d19zaW1wKSRuZXdfbmFtZSA9PSBpXSkKICAKICBpbnRyYSA9IGxlbmd0aChFKGdfd3dfc2ltcClbZ2V0LmVkZ2UuaWRzKGdfd3dfc2ltcCwgdnAgPSBjKGksIGkpKV0pCiAgb3JnID0gbGVuZ3RoKEUoZ193d19zaW1wKVtnZXQuZWRnZS5pZHMoZ193d19zaW1wLCB2cCA9IGMoaSwgIk9yZ2FuaXppbmcgVGVhbSIpKV0pCiAgaW50ZSA9IGRlZ3JlZShnX3d3X3NpbXAsIHYgPSBpKSAtICgyKmludHJhKSAtIG9yZwogIAogIGludHJhX3d0ID0gRShnX3d3X3NpbXApJHdlaWdodFtnZXQuZWRnZS5pZHMoZ193d19zaW1wLCB2cCA9IGMoaSwgaSkpXQogIG9yZ193dCA9IEUoZ193d19zaW1wKSR3ZWlnaHRbZ2V0LmVkZ2UuaWRzKGdfd3dfc2ltcCwgdnAgPSBjKGksICJPcmdhbml6aW5nIFRlYW0iKSldCiAgCiAgaWYobGVuZ3RoKG9yZ193dCkgPT0gMCkKICAgIG9yZ193dCA9IDAKICBpZihsZW5ndGgoaW50cmFfd3QpID09IDApCiAgICBpbnRyYV93dCA9IDAKICAKICBpbnRlX3d0ID0gc3RyZW5ndGgoZ193d19zaW1wLCB2ID0gaSkgLSAoMippbnRyYV93dCkgLSBvcmdfd3QKICAKICB0ZWFtX3d3ID0gcmJpbmQodGVhbV93dywgZGF0YS5mcmFtZSh0ZWFtID0gaSwgZGVuc2l0eV9pbnRyYV93dyA9IGlncmFwaDo6ZWRnZV9kZW5zaXR5KGcpLCBtZWFuX3N0cmVuZ3RoX2ludHJhX3d3ID0gaW50cmFfd3QvZWNvdW50KGcpLCBkZWdyZWVfaW50ZXJfd3cgPSBpbnRlLCBzdHJlbmd0aF9vcmdfcGVyX3BlcnNvbl93dyA9IG9yZ193dC92Y291bnQoZykpKQogIAp9CgpgYGAKCk5ldHdvcmsgUHJvcGVydGllcyAKCmBgYHtyfQoKdGVhbV9uZXRfbWVyZ2VkID0gZGF0YS5mcmFtZSgpCgprYl9wcm9wcyA9IGRhdGEuZnJhbWUodGVhbSA9IFYoZ19rYl9zaW1wKSRuYW1lLCBidXJ0X2tiID0gY29uc3RyYWludChnX2tiX3NpbXAsIHdlaWdodHMgPSBFKGdfa2Jfc2ltcCkkd2VpZ2h0KSwgY2xvc2VuZXNzX2tiID0gY2xvc2VuZXNzKGdfa2Jfc2ltcCwgd2VpZ2h0cyA9IDEvRShnX2tiX3NpbXApJHdlaWdodCwgbm9ybWFsaXplZCA9IFRSVUUpLCBiZXR3ZWVubmVzc19rYiA9IGJldHdlZW5uZXNzKGdfa2Jfc2ltcCwgd2VpZ2h0cyA9IDEvRShnX2tiX3NpbXApJHdlaWdodCwgbm9ybWFsaXplZCA9IFRSVUUpKQoKc2FfcHJvcHMgPSBkYXRhLmZyYW1lKHRlYW0gPSBWKGdfc2Ffc2ltcCkkbmFtZSwgYnVydF9zYSA9IGNvbnN0cmFpbnQoZ19zYV9zaW1wLCB3ZWlnaHRzID0gRShnX3NhX3NpbXApJHdlaWdodCksIGNsb3NlbmVzc19zYSA9IGNsb3NlbmVzcyhnX3NhX3NpbXAsIHdlaWdodHMgPSAxL0UoZ19zYV9zaW1wKSR3ZWlnaHQsIG5vcm1hbGl6ZWQgPSBUUlVFKSwgYmV0d2Vlbm5lc3Nfc2EgPSBiZXR3ZWVubmVzcyhnX3NhX3NpbXAsIHdlaWdodHMgPSAxL0UoZ19zYV9zaW1wKSR3ZWlnaHQsIG5vcm1hbGl6ZWQgPSBUUlVFKSkKCnd3X3Byb3BzID0gZGF0YS5mcmFtZSh0ZWFtID0gVihnX3d3X3NpbXApJG5hbWUsIGJ1cnRfd3cgPSBjb25zdHJhaW50KGdfd3dfc2ltcCwgd2VpZ2h0cyA9IEUoZ193d19zaW1wKSR3ZWlnaHQpLCBjbG9zZW5lc3Nfd3cgPSBjbG9zZW5lc3MoZ193d19zaW1wLCB3ZWlnaHRzID0gMS9FKGdfd3dfc2ltcCkkd2VpZ2h0LCBub3JtYWxpemVkID0gVFJVRSksIGJldHdlZW5uZXNzX3d3ID0gYmV0d2Vlbm5lc3MoZ193d19zaW1wLCB3ZWlnaHRzID0gMS9FKGdfd3dfc2ltcCkkd2VpZ2h0LCBub3JtYWxpemVkID0gVFJVRSkpCgp0ZWFtX25ldF9tZXJnZWQgPSBtZXJnZShrYl9wcm9wcywgc2FfcHJvcHMsIGJ5LnggPSAidGVhbSIsIGJ5LnkgPSAidGVhbSIsIGFsbC54ID0gVFJVRSwgYWxsLnkgPSBUUlVFKQp0ZWFtX25ldF9tZXJnZWQgPSBtZXJnZSh0ZWFtX25ldF9tZXJnZWQsIHd3X3Byb3BzLCBieS54ID0gInRlYW0iLCBieS55ID0gInRlYW0iLCBhbGwueCA9IFRSVUUsIGFsbC55ID0gVFJVRSkKCmBgYAoKCmIpIFRhc2tzIENvcnJlbGF0aW9ucyBhbmQgUmVndWxhcml0eQoKYGBge3J9Cgp0YXNrcyA9IG1lcmdlKHRhc2tzLCBtYXBbLGMoIkhhc2giLCAibmV3X25hbWUiKV0sIGJ5LnggPSAidXNlcl9oYXNoIiwgYnkueSA9ICJIYXNoIiwgYWxsLnggPSBUUlVFKQp0YXNrcyRUZWFtID0gdGFza3MkbmV3X25hbWUKCmEgPSAgcmVzaGFwZTI6OmFjYXN0KHRhc2tzLCB1c2VyX2hhc2h+dGFza3MsIGxlbmd0aCwgZHJvcCA9IEZBTFNFKQphW2E+MF0gPSAxICNJbnZvbHZlZCBpbiBhbiBhY3Rpdml0eSBvciBub3QKCmIgPSByZXNoYXBlMjo6YWNhc3QodGFza3MsIG5ld19uYW1lfnRhc2tzLCBsZW5ndGgsIGRyb3AgPSBGQUxTRSkKYltiPjBdID0gMQoKdGVhbV90YXNrX3N0YXRzID0gZGF0YS5mcmFtZSgpCgpmb3IgKGkgaW4gdW5pcXVlKG1hcCRuZXdfbmFtZSkpCnsKICBtZW0gPSBtYXAkSGFzaFttYXAkbmV3X25hbWUgPT0gaV0KICBzcyA9IGFbcm93bmFtZXMoYSkgJWluJSBtZW0sXQogIAogIHNiID0gYltyb3duYW1lcyhiKSA9PSBpLF0KICAKICBpZighaXMubnVsbChucm93KHNzKSkpCiAgewogICAgIHJzID0gcm93U3VtcyhzcykvbmNvbChzcykKICAgICBjcyA9IGNvbFN1bXMoc3MpL25yb3coc3MpCiAgfQogIAogIHRlYW1fdGFza19zdGF0cyA9IHJiaW5kKHRlYW1fdGFza19zdGF0cywgZGF0YS5mcmFtZSh0ZWFtID0gaSwgbWVhbl9wZXJzb25fcGVyX3Rhc2sgPSBtZWFuKGNzKSwgbWVhbl90YXNrX3Blcl9wZXJzb24gPSBtZWFuKHJzKSwgdGVhbV9hY3Rpdml0eV9zcGFuID0gc3VtKHNiKS9sZW5ndGgoc2IpKSkKICAKfSAKCnRhc2tzID0gdGFza3MgJT4lIHNlbGVjdCgtYygic3VydmV5X2lkX25vX2V4aXN0IiwgIm5ld19uYW1lIikpCgp3cml0ZS5jc3YodGFza3MsICIuLi9wcm9jZXNzZWQgZGF0YS9zdXJ2ZXlfdGFza3MuY3N2IikKCmBgYAoKUmVndWxhcml0eQoKYGBge3J9Cgp0YXNrcyA9IHRhc2tzICU+JSByb3d3aXNlKCkgJT4lIG11dGF0ZSh3ZWVrID0gc3Ryc3BsaXQoc3VydmV5X25hbWUsICI6IilbWzFdXVsxXSkKdGFza3Mkd2VlayA9IGZhY3Rvcih0YXNrcyR3ZWVrLCBsZXZlbHMgPSBjKCJXZWVrbHkgMSIsICJXZWVrbHkgMiIsICJXZWVrbHkgMyIsICJXZWVrbHkgNCIpKQoKdGVhbV9yZWcgPSBkYXRhLmZyYW1lKCkKCmZvciAoaSBpbiB1bmlxdWUodGFza3MkdGFza3MpKQp7CiAgCiAgYiA9IHJlc2hhcGUyOjphY2FzdCh0YXNrc1t0YXNrcyR0YXNrcyA9PSBpLCBjKCJUZWFtIiwgIndlZWsiKV0sIFRlYW1+d2VlaywgbGVuZ3RoLCBkcm9wID0gRkFMU0UpCiAgdGVhbV9yZWcgPSByYmluZCh0ZWFtX3JlZywgZGF0YS5mcmFtZSh0ZWFtID0gcm93bmFtZXMoYiksIHRhc2sgPSBpLCBub193ZWVrcyA9IGFwcGx5KGIsIDEsIGZ1bmN0aW9uKHgpIHN1bSh4PjApKSwgZ2luaSA9IGFwcGx5KGIsIDEsIGZ1bmN0aW9uKHgpIDEtaW5lcTo6R2luaSh4LCBjb3JyID0gVFJVRSkpKSkKCn0KCnRlYW1fcmVnX2F2ZyA9IHRlYW1fcmVnICU+JSBncm91cF9ieSh0ZWFtKSAlPiUgc3VtbWFyaXNlKG1lYW5fbndlZWtzX3Rhc2sgPSBtZWFuKG5vX3dlZWtzKSwgbWVhbl9naW5pX3Rhc2sgPSBtZWFuKGdpbmkpKQoKdCA9IHJlc2hhcGUyOjphY2FzdCh0YXNrcywgVGVhbX53ZWVrLCBsZW5ndGgsIGRyb3AgPSBGQUxTRSkKdGVhbV9yZWdfb3ZlcmFsbCA9IGRhdGEuZnJhbWUodGVhbSA9IHJvd25hbWVzKHQpLCBnaW5pX292ZXJhbGxfdGFzayA9IGFwcGx5KHQsIDEsIGZ1bmN0aW9uKHgpIDEtaW5lcTo6R2luaSh4LCBjb3JyID0gVFJVRSkpKQoKdGVhbV9yZWdfYXZnID0gbWVyZ2UodGVhbV9yZWdfYXZnLCB0ZWFtX3JlZ19vdmVyYWxsLCBieS54ID0gInRlYW0iLCBieS55PSAidGVhbSIsIGFsbC54ID0gVFJVRSwgYWxsLnkgPSBUUlVFKQoKYGBgCgoKMi4gU2xhY2sgTWV0cmljcwoKYGBge3J9Cgpsb2FkKCIuLi8uLi9FdmFsdWF0ZS9wcm9jZXNzZWQgZGF0YS9zbGFja19hbGxfaW50LlJEYXRhIikKCmRmX3RvdGFsID0gZGZfdG90YWxbZGZfdG90YWwkdGltZXN0YW1wIDw9IGFzLm51bWVyaWMoYXMuUE9TSVhjdCgiMjAyMS0xMS0zMCIsIG9yaWdpbiA9ICIxOTcwLTAxLTAxIikpLF0KZ19zbGFjayA9IGdyYXBoX2Zyb21fZGF0YV9mcmFtZShkZl90b3RhbFssYygzLDQsMSwyLDMpXSwgZGlyZWN0ZWQgPSBGQUxTRSkKRShnX3NsYWNrKSR3ZWlnaHQgPSAxCmdfc2xhY2tfc2ltcCA9IHNpbXBsaWZ5KGdfc2xhY2ssIHJlbW92ZS5sb29wcyA9IEZBTFNFKQoKdmVydGljZXMgPSByZWFkLmNzdigiLi4vLi4vRXZhbHVhdGUvcHJvY2Vzc2VkIGRhdGEvc2xhY2tfaWRfdmVyaWZpZWQuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUgZHJvcF9uYSgpCnZlcnRpY2VzJFRlYW1bdmVydGljZXMkVGVhbSA9PSAiVG9vbCBPd25lciJdID0gIk9yZ2FuaXppbmcgVGVhbSIKCmdfc2xhY2tfdXNlcnMgPSBncmFwaF9mcm9tX2RhdGFfZnJhbWUoZGZfdG90YWwsIHZlcnRpY2VzID0gdmVydGljZXNbLCBjKDMsMiw0LDUsNildLCBkaXJlY3RlZCA9IEZBTFNFKQpFKGdfc2xhY2tfdXNlcnMpJHdlaWdodCA9IDEKZ19zbGFja191c2Vyc19zaW1wID0gc2ltcGxpZnkoZ19zbGFja191c2VycywgcmVtb3ZlLmxvb3BzID0gVFJVRSkKCndyaXRlLmNzdihkZl90b3RhbCwgIi4uL3Byb2Nlc3NlZCBkYXRhL3NsYWNrX2ludGVyYWN0aW9ucy5jc3YiKQoKYGBgCgpgYGB7cn0KCnN0YXRzX3NsYWNrID0gZGF0YS5mcmFtZSgpCgpmb3IgKGkgaW4gVihnX3NsYWNrX3NpbXApJG5hbWUpCnsKICBpZiAoIWkgJWluJSBjKCJPcmdhbml6aW5nIFRlYW0iLCAiVG9vbCBPd25lciIpKQogIHsKICAgIAogICAgZyA9IGluZHVjZWRfc3ViZ3JhcGgoZ19zbGFja191c2Vyc19zaW1wLCB2aWRzID0gVihnX3NsYWNrX3VzZXJzX3NpbXApW1YoZ19zbGFja191c2Vyc19zaW1wKSRUZWFtID09IGldKQogICAgCiAgICBpbnRyYSA9IGxlbmd0aChFKGdfc2xhY2tfc2ltcClbZ2V0LmVkZ2UuaWRzKGdfc2xhY2tfc2ltcCwgdnAgPSBjKGksIGkpKV0pCiAgICBvcmcgPSBsZW5ndGgoRShnX3NsYWNrX3NpbXApW2dldC5lZGdlLmlkcyhnX3NsYWNrX3NpbXAsIHZwID0gYyhpLCAiT3JnYW5pemluZyBUZWFtIikpXSkKICAgIGludGUgPSBkZWdyZWUoZ19zbGFja19zaW1wLCB2ID0gaSkgLSAyKmludHJhIC0gb3JnCiAgICAKICAgIGludHJhX3d0ID0gRShnX3NsYWNrX3NpbXApJHdlaWdodFtnZXQuZWRnZS5pZHMoZ19zbGFja19zaW1wLCB2cCA9IGMoaSwgaSkpXQogICAgb3JnX3d0ID0gRShnX3NsYWNrX3NpbXApJHdlaWdodFtnZXQuZWRnZS5pZHMoZ19zbGFja19zaW1wLCB2cCA9IGMoaSwgIk9yZ2FuaXppbmcgVGVhbSIpKV0KICAgIAogICAgaWYgKGxlbmd0aChpbnRyYV93dCkgPT0gMCkKICAgICAgaW50cmFfd3QgPSAwCiAgICBpZiAobGVuZ3RoKG9yZ193dCkgPT0gMCkKICAgICAgb3JnX3d0ID0gMAogICAgCiAgICBpbnRlX3d0ID0gc3RyZW5ndGgoZ19zbGFja19zaW1wLCB2aWRzID0gaSkgLSAyKmludHJhX3d0IC0gb3JnX3d0CiAgICAKICAgIGVkID0gaW50cmEvZWNvdW50KGcpCiAgICBpZiAoaXMubmFuKGVkKSkKICAgICAgZWQgPSAwCiAgICAKICAgIHN0YXRzX3NsYWNrID0gcmJpbmQoc3RhdHNfc2xhY2ssIGRhdGEuZnJhbWUodGVhbSA9IGksIGRlbnNpdHlfaW50cmFfc2xhY2sgPSBlZGdlX2RlbnNpdHkoZyksIHN0cmVuZ3RoX2ludHJhX3NsYWNrID0gaW50cmFfd3QsIG1lYW5fc3RyZW5ndGhfaW50cmFfc2xhY2sgPSBlZCwgZGVncmVlX2ludGVyX3NsYWNrID0gaW50ZSwgc3RyZW5ndGhfaW50ZXJfc2xhY2sgPSBpbnRlX3d0LCBzdHJlbmd0aF9vcmdfc2xhY2sgPSBvcmdfd3QpKQogIH0KfQoKc3RhdHNfc2xhY2sgPSBtZXJnZShzdGF0c19zbGFjaywgcmVnX21hcCwgYnkueCA9ICJ0ZWFtIiwgYnkueSA9ICJvbGRfbmFtZSIsIGFsbC54ID0gVFJVRSkKCmBgYAoKR2VuZXJhbCBTbGFjayBQcm9wcwoKYGBge3J9Cgp0ZXh0cyA9IHRleHRzW3RleHRzJHRpbWVzdGFtcCA8PSBhcy5QT1NJWGN0KCIyMDIxLTExLTMwIiwgb3JpZ2luID0gIjE5NzAtMDEtMDEiKSxdCnQgPSB0ZXh0cyAlPiUgZ3JvdXBfYnkoVGVhbSkgJT4lIHN1bW1hcmlzZShjb3VudF9zbGFjayA9IG4oKSkKCnRlYW1fc2xhY2sgPSBkYXRhLmZyYW1lKHRlYW0gPSBWKGdfc2xhY2tfc2ltcCkkbmFtZSwgYnVydF9zbGFjayA9IGNvbnN0cmFpbnQoZ19zbGFja19zaW1wLCB3ZWlnaHRzID0gRShnX3NsYWNrX3NpbXApJHdlaWdodCksIGJldHdlZW5uZXNzX3NsYWNrID0gYmV0d2Vlbm5lc3MoZ19zbGFja19zaW1wLCB3ZWlnaHRzID0gMS9FKGdfc2xhY2tfc2ltcCkkd2VpZ2h0LCBub3JtYWxpemVkID0gVFJVRSksIGNsb3NlbmVzc19zbGFjayA9IGNsb3NlbmVzcyhnX3NsYWNrX3NpbXAsIHdlaWdodHMgPSAxL0UoZ19zbGFja19zaW1wKSR3ZWlnaHQsIG5vcm1hbGl6ZWQgPSBUUlVFKSkKCnRlYW1fc2xhY2sgPSBtZXJnZSh0ZWFtX3NsYWNrLCB0LCBieS54ID0gInRlYW0iLCBieS55ID0gIlRlYW0iLCBhbGwueCA9IFRSVUUsIGFsbC55ID0gVFJVRSkKdGVhbV9zbGFjayRjb3VudFtpcy5uYSh0ZWFtX3NsYWNrJGNvdW50KV0gPSAwCnRlYW1fc2xhY2sgPSB0ZWFtX3NsYWNrWyF0ZWFtX3NsYWNrJHRlYW0gJWluJSBjKCJPcmdhbml6aW5nIFRlYW0iLCAiVG9vbCBPd25lciIpLF0KCnRlYW1fc2xhY2sgPSBtZXJnZSh0ZWFtX3NsYWNrLCByZWdfbWFwLCBieS54ID0gInRlYW0iLCBieS55ID0gIm9sZF9uYW1lIiwgYWxsLnggPSBUUlVFKQoKd3JpdGUuY3N2KHRleHRzLCAiLi4vcHJvY2Vzc2VkIGRhdGEvc2xhY2tfbWVzc2FnZXMuY3N2IikKCmBgYAoKCjMuIERpdmVyc2l0eSBNZXRyaWNzCgpgYGB7cn0KCnNoYW5ub24gPSBmdW5jdGlvbihsaXN0KQp7CiAgZW50ID0gMAogIGZvciAoaSBpbiB1bmlxdWUobGlzdCkpCiAgewogICAgdCA9IHN1bShsaXN0ID09IGkpCiAgICBuID0gbGVuZ3RoKGxpc3QpCiAgICBlbnQgPSBlbnQgKyAodC9uKSpsb2codC9uKQogIH0KICAKICByZXR1cm4oLTEqZW50KQp9CgpyZWckYWdlID0gZmxvb3IoYXMubnVtZXJpYyhkaWZmdGltZShhcy5EYXRlKCIyMDIyLTA0LTAxIiksIGFzLkRhdGUocmVnJGJpcnRoZGF5LCB0cnlGb3JtYXRzID0gYygiJW0vJWQvJVkiKSksIHVuaXQ9IndlZWtzIikpLzUyLjI1KQptZXRyaWNzID0gZGF0YS5mcmFtZShUZWFtID0gdW5pcXVlKHJlZyRuZXdfbmFtZSkpCgpmb3IgKGkgaW4gYygiZ2VuZGVyIiwgImNvdW50cnlfb3JpZyIsICJjb3VudHJ5X3Jlc2lkIiwgImVkdWNhdGlvbiIsICJjb21tdW5pY2F0aW9uIiwgImV4YW50ZV9wcm9qZWN0X1NERyIsICJiYWNrZ3JvdW5kIiwgIm9jY3VwYXRpb24iKSkKewogIHRlbXAgPSByZWdbLGMoIm5ld19uYW1lIiwgaSldCiAgdGVtcCA9IGNsZWFuX3NwbGl0X21jcSh0ZW1wKQogIGNvbG5hbWVzKHRlbXApID0gYygiVGVhbSIsICJ2YXIiKQogIAoKICB0ID0gdGVtcCAlPiUgZ3JvdXBfYnkoVGVhbSkgJT4lIHN1bW1hcmlzZShzaGFubm9uID0gc2hhbm5vbih2YXIpLCBzcGFuID0gbGVuZ3RoKHVuaXF1ZSh2YXIpKSkKICBjb2xuYW1lcyh0KSA9IGMoIlRlYW0iLCBwYXN0ZShpLCAiX3NoYW5ub24iLCBzZXAgPSAnJyksIHBhc3RlKGksICJfc3BhbiIsIHNlcCA9ICcnKSkKICAKICBtZXRyaWNzID0gbWVyZ2UobWV0cmljcywgdCwgYnkueCA9ICJUZWFtIiwgYnkueSA9ICJUZWFtIiwgYWxsLnggPSBUUlVFLCBhbGwueSA9IFRSVUUpCiAgCn0KCm1ldHJpY3MgPSBtZXJnZShtZXRyaWNzLCB0ZWFtcywgYnkueCA9ICJUZWFtIiwgYnkueSA9ICJUZWFtIE5hbWUiLCBhbGwueCA9IFRSVUUpCgpyZWckZWR1Y2F0aW9uX2NvZGUgPSAwCnJlZyRlZHVjYXRpb25fY29kZVtyZWckZWR1Y2F0aW9uID09ICJIaWdoc2Nob29sIl0gPSAxCnJlZyRlZHVjYXRpb25fY29kZVtyZWckZWR1Y2F0aW9uID09ICJVbml2ZXJzaXR5IChVbmRlcmdyYWR1YXRlIC8gQmFjaGVsb3JzKSJdID0gMgpyZWckZWR1Y2F0aW9uX2NvZGVbcmVnJGVkdWNhdGlvbiA9PSAiVW5pdmVyc2l0eSAoR3JhZHVhdGUgLyBNYXN0ZXJzKSJdID0gMwoKCmFnZSA9IHJlZ1ssYygibmV3X25hbWUiLCAiYWdlIiwgImV4YW50ZV9wcm9qZWN0IiwgImVkdWNhdGlvbl9jb2RlIildICU+JSBncm91cF9ieShuZXdfbmFtZSkgJT4lIHN1bW1hcmlzZShtZWFuX2FnZSA9IG1lYW4oYWdlKSwgbWVhbl9leGFudGUgPSBzdW0oZXhhbnRlX3Byb2plY3QgPT0gIlllcyIpL2xlbmd0aChleGFudGVfcHJvamVjdCksIGFnZV9nYXAgPSBtYXgoYWdlKSAtIG1pbihhZ2UpLCBtZWFuX2VkdWNhdGlvbiA9IG1lYW4oZWR1Y2F0aW9uX2NvZGUpKQoKbWV0cmljcyA9IG1lcmdlKG1ldHJpY3MsIGFnZSwgYnkueCA9ICJUZWFtIiwgYnkueSA9ICJuZXdfbmFtZSIsIGFsbC54ID0gVFJVRSwgYWxsLnkgPSBUUlVFKQptZXRyaWNzJHRlYW0gPSBtZXRyaWNzJFRlYW0KCgptZXRyaWNzID0gbWV0cmljcyAlPiUgc2VsZWN0KC1jKCJUZWFtIiwgIlN0YWdlIiwgIlR5cGUiKSkKCmBgYAoKKioqKioqKioqKioqKioqKioqKioqKioqCgpDb3JyZWxhdGlvbnMKCgpgYGB7cn0KCnggPSBjb2xuYW1lcyhvdXRjb21lKQp4ID0geFsheCAlaW4lIGMoIlRlYW0iLCAiU3RhZ2UiLCAiVHlwZSIpXQoKb3V0Y29tZSRgRGF0YSBDb2xsZWN0aW9uIGFuZCBOU09gW2lzLm5hKG91dGNvbWUkYERhdGEgQ29sbGVjdGlvbiBhbmQgTlNPYCldID0gMAoKdGVtcF9vdXRjb21lID0gb3V0Y29tZQpMb1MgPSAwLjEKCmBgYAoKRnVuY3Rpb24gZm9yIGNvbXB1dGluZyB0aGUgY29ycmVsYXRpb24gbWF0cml4CgpgYGB7cn0KCmNvcnJfbWF0cml4ID0gZnVuY3Rpb24obWF0cml4LCBjb2xuYW1lczEsIGNvbG5hbWVzMikKewogIGRmX2NvcnIgPSBkYXRhLmZyYW1lKCkKICAKICBmb3IgKGkgaW4gY29sbmFtZXMxKQogIHsKICAgIGZvciAoaiBpbiBjb2xuYW1lczIpCiAgICB7CiAgICAgIGMgPSBjb3IudGVzdChtYXRyaXhbLGpdLCBtYXRyaXhbLGldKQogICAgICBkZl9jb3JyID0gcmJpbmQoZGZfY29yciwgZGF0YS5mcmFtZShpID0gaSwgaiA9IGosIGNvciA9IGMkZXN0aW1hdGUsIHBfdmFsID0gYyRwLnZhbHVlKSkKICAgIH0KICB9CiAgCiAgcmV0dXJuKGRmX2NvcnIpCn0KCgpldmFsX3JhbmRvbWl6ZWQgPSBmdW5jdGlvbihjb2wxLCBjb2wyLCBuID0gMTAwMCkKewogIGRmX3JhbmQgPSBkYXRhLmZyYW1lKCkKICAKICBmb3IgKGkgaW4gMTpuKQogIHsKICAgIGMgPSBjb3IudGVzdChzYW1wbGUoY29sMSksIGNvbDIpCiAgICBkZl9yYW5kID0gcmJpbmQoZGZfcmFuZCwgZGF0YS5mcmFtZShpdGVyYXRpb24gPSBpLCBwX3ZhbCA9IGMkcC52YWx1ZSwgY29yID0gYyRlc3RpbWF0ZSkpCiAgfQogIAogICNyZXR1cm4oc3VtKGRmX3JhbmQkcF92YWwgPD0gTG9TKS9uKQogIHJldHVybihkZl9yYW5kJGNvcikKICAKfQoKYGBgCgoKCioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCgpgYGB7cn0KCmRmX2xpc3QgPSBsaXN0KCJrbm93bl9iZWZvcmUiID0gdGVhbV9rYiwgInNlZWtfYWR2aWNlIiA9IHRlYW1fc2EsICJ3b3JrX3dpdGgiID0gdGVhbV93dywgIm1lcmdlZF9uZXR3b3JrIiA9IHRlYW1fbmV0X21lcmdlZCwgIm1lcmdlZF9zbGFjayIgPSB0ZWFtX3NsYWNrLCAic2xhY2tfc3RhdGlzdGljcyIgPSBzdGF0c19zbGFjaywgInRlYW1fdGFza19zdGF0cyIgPSB0ZWFtX3Rhc2tfc3RhdHMsICJ0YXNrX3JlZ3VsYXJpdHkiID0gdGVhbV9yZWdfYXZnLCAiZGl2ZXJzaXR5X21ldHJpY3MiID0gbWV0cmljcykKCmRmX3NpZyA9IGRhdGEuZnJhbWUoKQoKZm9yIChpIGluIDE6bGVuZ3RoKGRmX2xpc3QpKQp7CiAgcGRmKHBhc3RlKCIuLi9maWd1cmVzL2NvcnJlbGF0aW9ucy8iLCBuYW1lcyhkZl9saXN0KVtpXSwgIl9vdXRjb21lLnBkZiIsIHNlcCA9ICIiKSwgaGVpZ2h0ID0gMTAsIHdpZHRoID0gMTIpCiAgCiAgdGVtcF9vdXRjb21lJFRlYW0gPSBzYW1wbGUodGVtcF9vdXRjb21lJFRlYW0pCiAgCiAgZGYgPSBkZl9saXN0W1tpXV0KICB5ID0gY29sbmFtZXMoZGYpCiAgCiAgaWYgKCJuZXdfbmFtZSIgJWluJSB5KQogICAgZGYkdGVhbSA9IGRmJG5ld19uYW1lCiAgCiAgdGVtcCA9IG1lcmdlKGRmWyFkZiR0ZWFtICVpbiUgYygiT3JnYW5pemluZyBUZWFtIiwgIkM1OiBBc2hpZmEgTmF6cmluIiksXSwgb3V0Y29tZSwgYnkueCA9ICJ0ZWFtIiwgYnkueSA9ICJUZWFtIiwgYWxsLnggPSBUUlVFLCBhbGwueSA9IFRSVUUpCiAgdGVtcF9yYW5kID0gbWVyZ2UoZGZbIWRmJHRlYW0gJWluJSBjKCJPcmdhbml6aW5nIFRlYW0iLCAiQzU6IEFzaGlmYSBOYXpyaW4iKSxdLCB0ZW1wX291dGNvbWUsIGJ5LnggPSAidGVhbSIsIGJ5LnkgPSAiVGVhbSIsIGFsbC54ID0gVFJVRSwgYWxsLnkgPSBUUlVFKQogIAogIGRmX2NvcnIgPSBjb3JyX21hdHJpeCh0ZW1wLCB4LCB5WyF5ICVpbiUgYygidGVhbSIsICJuZXdfbmFtZSIpXSkKICBkZl9jb3JyX3JhbmQgPSBjb3JyX21hdHJpeCh0ZW1wX3JhbmQsIHgsIHlbIXkgJWluJSBjKCJ0ZWFtIiwgIm5ld19uYW1lIildKQogIAogIGRmX2NvcnIkY29yW2RmX2NvcnIkcF92YWwgPiBMb1NdID0gMAogIGRmX2NvcnIkY29yID0gcm91bmQoZGZfY29yciRjb3IsIDMpCgogIGRmX2NvcnJfcmFuZCRjb3JbZGZfY29ycl9yYW5kJHBfdmFsID4gTG9TXSA9IDAKICBkZl9jb3JyX3JhbmQkY29yID0gcm91bmQoZGZfY29ycl9yYW5kJGNvciwgMykKICAKICBwbHQgPSBnZ3Bsb3QoZGZfY29ycikgKyBnZW9tX3RpbGUoYWVzKHggPSBqLCB5ID0gaSwgZmlsbCA9IGNvciksIGx3ZCA9IDEuNSwgbGluZXR5cGUgPSAxKSArIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKGxvdyA9ICJibHVlIiwgaGlnaCA9ICJyZWQiKSArIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE1KSArICAgIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsgeWxhYigiIikgKyB4bGFiKCIiKSArIGdlb21fdGV4dChhZXMoeCA9IGosIHkgPSBpLCBsYWJlbCA9IGNvcikpICsKICBnZ3RpdGxlKHBhc3RlKG5hbWVzKGRmX2xpc3QpW2ldLCAiIHZzIE91dGNvbWUiLCBzZXAgPSAiIikpCiAgCiAgaWYgKGxlbmd0aCh5KSA+IDUpCiAgICBwbHQgPSBwbHQgKyB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKICAKICAjZ2dzYXZlKHBsdCwgZmlsZW5hbWUgPSBwYXN0ZSgiLi4vZmlndXJlcy9jb3JyZWxhdGlvbnMvIiwgbmFtZXMoZGZfbGlzdClbaV0sICJfb3V0Y29tZS5wbmciLCBzZXAgPSAiIiksIHdpZHRoID0gMTIsIGhlaWdodCA9IDcpCiAgcHJpbnQocGx0KQogIAogIHBsdCA9IGdncGxvdChkZl9jb3JyX3JhbmQpICsgZ2VvbV90aWxlKGFlcyh4ID0gaiwgeSA9IGksIGZpbGwgPSBjb3IpLCBsd2QgPSAxLjUsIGxpbmV0eXBlID0gMSkgKyBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiYmx1ZSIsIGhpZ2ggPSAicmVkIikgKyB0aGVtZV9idyhiYXNlX3NpemUgPSAxNSkgKyAgICAKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArIHlsYWIoIiIpICsgeGxhYigiIikgKyBnZW9tX3RleHQoYWVzKHggPSBqLCB5ID0gaSwgbGFiZWwgPSBjb3IpKSArCiAgZ2d0aXRsZShwYXN0ZShuYW1lcyhkZl9saXN0KVtpXSwgIiB2cyBPdXRjb21lIFJhbmQiLCBzZXAgPSAiIikpCiAgCiAgaWYgKGxlbmd0aCh5KSA+IDUpCiAgICBwbHQgPSBwbHQgKyB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKICAKICAjZ2dzYXZlKHBsdCwgZmlsZW5hbWUgPSBwYXN0ZSgiLi4vZmlndXJlcy9yYW5kX2NvcnJlbGF0aW9ucy8iLCBuYW1lcyhkZl9saXN0KVtpXSwgIl9vdXRjb21lX3JhbmQucG5nIiwgc2VwID0gIiIpLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3KQogIHByaW50KHBsdCkKICAKICBkZXYub2ZmKCkKICAKICBkZl9zaWcgPSByYmluZChkZl9zaWcsIGRmX2NvcnJbZGZfY29yciRwX3ZhbCA8PSBMb1MsIGMoImkiLCJqIildKQogIAp9CgpkZl9zaWcgPSBkZl9zaWcgJT4lIGRyb3BfbmEoKQoKYGBgCgoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKCkxpbmVhciBNb2RlbAoKYGBge3J9CmtiID0gdGVhbV9rYlssIGMoInRlYW0iLCAibWF4X2NvbXBvbmVudHMiKV0Kc2EgPSB0ZWFtX3NhWywgYygiZGVncmVlX2ludGVyX3NhIiwgImRlbnNpdHlfaW50cmFfc2EiLCAidGVhbSIpXQojY29sbmFtZXMoc2EpID0gYygiZGVncmVlX2ludGVyX3NhIiwgImRlbnNpdHlfaW50cmFfc2EiLCAidGVhbSIpCnd3ID0gdGVhbV93d1ssIGMoIm1lYW5fc3RyZW5ndGhfaW50cmFfd3ciLCAidGVhbSIpXQojY29sbmFtZXMod3cpID0gYygibWVhbl9zdHJlbmd0aF9pbnRyYV93dyIsICJ0ZWFtIikKCnRzID0gdGVhbV9zbGFja1ssIGMoIm5ld19uYW1lIiwgImJ1cnRfc2xhY2siLCAiY2xvc2VuZXNzX3NsYWNrIiwgImNvdW50X3NsYWNrIildCmNvbG5hbWVzKHRzKSA9IGMoInRlYW0iLCAiYnVydF9zbGFjayIsICJjbG9zZW5lc3Nfc2xhY2siLCAibm9fbWVzc2FnZXNfc2xhY2siKQpzcyA9IHN0YXRzX3NsYWNrWywgYygibmV3X25hbWUiLCAic3RyZW5ndGhfaW50cmFfc2xhY2siLCAiZGVncmVlX2ludGVyX3NsYWNrIiwgInN0cmVuZ3RoX2ludGVyX3NsYWNrIiwgInN0cmVuZ3RoX29yZ19zbGFjayIpXQpjb2xuYW1lcyhzcykgPSBjKCJ0ZWFtIiwgInN0cmVuZ3RoX2ludHJhX3NsYWNrIiwgImRlZ3JlZV9pbnRlcl9zbGFjayIsICJzdHJlbmd0aF9pbnRlcl9zbGFjayIsICJzdHJlbmd0aF9vcmdfc2xhY2siKQoKdHJhID0gdGVhbV9yZWdfYXZnWywgYygidGVhbSIsICJtZWFuX253ZWVrc190YXNrIiwgIm1lYW5fZ2luaV90YXNrIiwgImdpbmlfb3ZlcmFsbF90YXNrIildCiNjb2xuYW1lcyh0cmEpID0gYygidGVhbSIsICJtZWFuX253ZWVrc190YXNrIiwgIm1lYW5fZ2luaV90YXNrIiwgImdpbmlfb3ZlcmFsbF90YXNrIikKCnRlbXAgPSBzYQp0ZW1wID0gbWVyZ2UodGVtcCwga2IsIGJ5LnggPSAidGVhbSIsIGJ5LnkgPSAidGVhbSIsIGFsbC54ID0gVFJVRSwgYWxsLnkgPSBUUlVFKQp0ZW1wID0gbWVyZ2UodGVtcCwgd3csIGJ5LnggPSAidGVhbSIsIGJ5LnkgPSAidGVhbSIsIGFsbC54ID0gVFJVRSwgYWxsLnkgPSBUUlVFKQp0ZW1wID0gbWVyZ2UodGVtcCwgdGVhbV9uZXRfbWVyZ2VkWywgYygidGVhbSIsICJidXJ0X3NhIiwgImNsb3NlbmVzc19zYSIpXSwgYnkueCA9ICJ0ZWFtIiwgYnkueSA9ICJ0ZWFtIiwgYWxsLnggPSBUUlVFLCBhbGwueSA9IFRSVUUpCnRlbXAgPSBtZXJnZSh0ZW1wLCB0cywgYnkueCA9ICJ0ZWFtIiwgYnkueSA9ICJ0ZWFtIiwgYWxsLnggPSBUUlVFLCBhbGwueSA9IFRSVUUpCnRlbXAgPSBtZXJnZSh0ZW1wLCBzcywgYnkueCA9ICJ0ZWFtIiwgYnkueSA9ICJ0ZWFtIiwgYWxsLnggPSBUUlVFLCBhbGwueSA9IFRSVUUpCnRlbXAgPSBtZXJnZSh0ZW1wLCB0ZWFtX3Rhc2tfc3RhdHNbLGMoIm1lYW5fdGFza19wZXJfcGVyc29uIiwgInRlYW0iLCAidGVhbV9hY3Rpdml0eV9zcGFuIildLCBieS54ID0gInRlYW0iLCBieS55ID0gInRlYW0iLCBhbGwueCA9IFRSVUUsIGFsbC55ID0gVFJVRSkKdGVtcCA9IG1lcmdlKHRlbXAsIHRyYSwgYnkueCA9ICJ0ZWFtIiwgYnkueSA9ICJ0ZWFtIiwgYWxsLnggPSBUUlVFLCBhbGwueSA9IFRSVUUpCnRlbXAgPSBtZXJnZSh0ZW1wLCBtZXRyaWNzWywgYygiZ2VuZGVyX3NoYW5ub24iLCAiZWR1Y2F0aW9uX3NoYW5ub24iLCAidGVhbSIsICJiYWNrZ3JvdW5kX3NwYW4iLCAic2l6ZSIsICJtZWFuX2FnZSIsICJtZWFuX2V4YW50ZSIsICJhZ2VfZ2FwIiwgIm1lYW5fZWR1Y2F0aW9uIildLCBieS54ID0gInRlYW0iLCBieS55ID0gInRlYW0iLCBhbGwueCA9IFRSVUUsIGFsbC55ID0gVFJVRSkKCnRlbXAgPSB0ZW1wWyF0ZW1wJHRlYW0gJWluJSBjKCJPcmdhbml6aW5nIFRlYW0iLCAiQzU6IEFzaGlmYSBOYXpyaW4iLCBOQSksXQojdGVtcCA9IG1lcmdlKHRlbXAsIG91dGNvbWVbLGMoIlRlYW0iLCAiZm9ybWF0aW9uIildLCBieS54ID0gInRlYW0iLCBieS55ID0gIlRlYW0iLCBhbGwueCA9IFRSVUUsIGFsbC55ID0gVFJVRSkKCmRmX2tleV9hdHRyaWJ1dGVzID0gdGVtcAoKYGBgCgpMaW5lYXIgTW9kZWxzIGZvciBkaWZmZXJlbnQgb3V0Y29tZSB2YXJpYWJsZXMKCmBgYHtyLCBldmFsID0gRkFMU0V9Cgpmb3IgKGkgaW4gYygiVG90YWwiLCAiV2Vla2x5IEV2YWx1YXRpb24iLCAiQ29tbWl0bWVudCIgLCAiQXR0ZW5kYW5jZSIsICJEZWxpdmVyYWJsZXMiLCAiRmluYWwgUGl0Y2giLCAibWVhbl9ub3ZlbHR5IiwgIm1lYW5fcmVsZXZhbmNlIiwgIm1lYW5fZmVhc2liaWxpdHkiLCAibWVhbl9jcm93ZHNvdXJjaW5nIiwgIm1lYW5fcHJlc2VudGF0aW9uIikpCnsKICBtb2RfdGVtcCA9IG1lcmdlKHRlbXAsIG91dGNvbWVbLGMoaSwgIlRlYW0iKV0sIGJ5LnggPSAidGVhbSIsIGJ5LnkgPSAiVGVhbSIsIGFsbC54ID0gVFJVRSwgYWxsLnkgPSBUUlVFKQogIHYgPSBkZl9zaWdbZGZfc2lnJGkgPT0gaSxdCiAgCiAgbGlzdCA9IGFzLmNoYXJhY3Rlcih2JGopCiAgbGlzdCA9IGxpc3RbbGlzdCAlaW4lIGNvbG5hbWVzKHRlbXApXQogIAogIGZvcm11bGEgPSBwYXN0ZShwYXN0ZShpLCAiIH4gIiwgc2VwID0gIiIpLCBnc3ViKCIsIiwgIisiLCAodG9TdHJpbmcobGlzdCkpKSwgc2VwID0gIiIpCiAgCiAgbW9kID0gbG0oZGF0YSA9IG1vZF90ZW1wWyxjKGksIGxpc3QpXSwgZm9ybXVsYSA9IGFzLmZvcm11bGEoZm9ybXVsYSkpCiAgCn0KCmBgYApgYGB7cn0KCm1vZF90b3RhbCA9IG1lcmdlKHRlbXAsIG91dGNvbWVbLGMoIlRvdGFsIiwgImZvcm1hdGlvbiIsICJzdGFnZV9wcm9ncmVzc2VkIiwiVGVhbSIpXSwgYnkueCA9ICJ0ZWFtIiwgYnkueSA9ICJUZWFtIiwgYWxsLnggPSBUUlVFLCBhbGwueSA9IFRSVUUpCgptb2QgPSBsbShkYXRhID0gbW9kX3RvdGFsLCBmb3JtdWxhID0gVG90YWwgfiBtZWFuX3N0cmVuZ3RoX2ludHJhX3d3ICsgYnVydF9zYSArICBjbG9zZW5lc3Nfc2xhY2sgKyBnaW5pX292ZXJhbGxfdGFzayArIHN0cmVuZ3RoX2ludGVyX3NsYWNrICsgc3RyZW5ndGhfb3JnX3NsYWNrKQoKcGxvdF9tb2RlbChtb2QsIHR5cGUgPSAic3RkMiIsIHNvcnQuZXN0ID0gVFJVRSwgdmxpbmUuY29sb3IgPSAiZ3JleTgwIiwgc2hvdy52YWx1ZXMgPSBUUlVFLCB2YWx1ZS5vZmZzZXQgPSAwLjMsIHRpdGxlID0gIiIpICsgdGhlbWVfYncoYmFzZV9zaXplID0gMTUpCgoKYGBgCgoKYGBge3J9Cgptb2QgPSBsbShkYXRhID0gbW9kX3RvdGFsLCBmb3JtdWxhID0gVG90YWwgfiBtZWFuX2FnZSArIGFnZV9nYXApCgpwbG90X21vZGVsKG1vZCwgdHlwZSA9ICJzdGQyIiwgc29ydC5lc3QgPSBUUlVFLCB2bGluZS5jb2xvciA9ICJncmV5ODAiLCBzaG93LnZhbHVlcyA9IFRSVUUsIHZhbHVlLm9mZnNldCA9IDAuMywgdGl0bGUgPSAiIikgKyB0aGVtZV9idyhiYXNlX3NpemUgPSAxNSkKCm1vZCA9IGxtKGRhdGEgPSBtb2RfdG90YWwsIGZvcm11bGEgPSBmb3JtYXRpb24gfiBtZWFuX2FnZSArIGFnZV9nYXApCgpwbG90X21vZGVsKG1vZCwgdHlwZSA9ICJzdGQyIiwgc29ydC5lc3QgPSBUUlVFLCB2bGluZS5jb2xvciA9ICJncmV5ODAiLCBzaG93LnZhbHVlcyA9IFRSVUUsIHZhbHVlLm9mZnNldCA9IDAuMywgdGl0bGUgPSAiZm9ybWF0aW9uIikgKyB0aGVtZV9idyhiYXNlX3NpemUgPSAxNSkKCm1vZCA9IGxtKGRhdGEgPSBtb2RfdG90YWwsIGZvcm11bGEgPSBzdGFnZV9wcm9ncmVzc2VkIH4gbWVhbl9hZ2UgKyBhZ2VfZ2FwKQoKcGxvdF9tb2RlbChtb2QsIHR5cGUgPSAic3RkMiIsIHNvcnQuZXN0ID0gVFJVRSwgdmxpbmUuY29sb3IgPSAiZ3JleTgwIiwgc2hvdy52YWx1ZXMgPSBUUlVFLCB2YWx1ZS5vZmZzZXQgPSAwLjMsIHRpdGxlID0gInN0YWdlX3Byb2dyZXNzZWQiKSArIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE1KQoKCmBgYAoKYGBge3J9CgpsID0geFsheCAlaW4lIGMoIm1lYW5fcHJlc2VudGF0aW9uIildCgpjZCA9IGNvcnJfbWF0cml4KG91dGNvbWUsIGwsIGwpCgpjZCRjb3JbY2QkcF92YWwgPiAwLjA1XSA9IDAKY2QkY29yID0gcm91bmQoY2QkY29yLCAzKQoKcGx0ID0gZ2dwbG90KGNkKSArIGdlb21fdGlsZShhZXMoeCA9IGosIHkgPSBpLCBmaWxsID0gY29yKSwgbHdkID0gMS41LCBsaW5ldHlwZSA9IDEpICsgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBoaWdoID0gInJlZCIpICsgdGhlbWVfYncoYmFzZV9zaXplID0gMTUpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKyB5bGFiKCIiKSArIHhsYWIoIiIpICsgZ2VvbV90ZXh0KGFlcyh4ID0gaiwgeSA9IGksIGxhYmVsID0gY29yKSkgKyBnZ3RpdGxlKCJNdWx0aWNvbGxpbmVhcml0eSBDaGVjayIpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgpnZ3Bsb3RseShwbHQpCgpgYGAKCmBgYHtyfQoKdCA9IGRmX2tleV9hdHRyaWJ1dGVzWywgYygidGVhbSIsICJzaXplIiwgImFnZV9nYXAiLCAiYmFja2dyb3VuZF9zcGFuIiwgIm1lYW5fZWR1Y2F0aW9uIiwibWVhbl9leGFudGUiLCAibm9fbWVzc2FnZXNfc2xhY2siLCAic3RyZW5ndGhfb3JnX3NsYWNrIiwgImNsb3NlbmVzc19zbGFjayIsICJtYXhfY29tcG9uZW50cyIsICJtZWFuX3N0cmVuZ3RoX2ludHJhX3d3IiwgImJ1cnRfc2EiLCAiZGVncmVlX2ludGVyX3NhIiwgInRlYW1fYWN0aXZpdHlfc3BhbiIsICJnaW5pX292ZXJhbGxfdGFzayIsICJtZWFuX3Rhc2tfcGVyX3BlcnNvbiIpXQoKY29sbmFtZXModCkgPSBjKCJ0ZWFtIiwgInRlYW1fc2l6ZSIsICJhZ2VfZ2FwIiwgImJhY2tncm91bmRfc3BhbiIsICJtZWFuX2VkdWNhdGlvbl9sZXZlbCIsICJwcmlvcl9zZGdfZXhwZXJpZW5jZSIsICJhY3Rpdml0eV9zbGFjayIsICJzdHJlbmd0aF9vcmdfc2xhY2siLCAiY2xvc2VuZXNzX3NsYWNrIiwgImZyYWN0aW9uX2NvbXBvbmVudF9rbm93bl9iZWZvcmUiLCAiY29sbGFib3JhdGlvbnNfaW50cmFfdGVhbSIsICJidXJ0X3NlZWtfYWR2aWNlIiwgImRlZ3JlZV9pbnRlcl9zZWVrX2R2aWNlIiwgInRlYW1fYWN0aXZpdHlfc3BhbiIsICJhY3Rpdml0eV9yZWd1bGFyaXR5IiwgIm1lYW5fdGFza19wZXJfcGVyc29uIikKCndyaXRlLmNzdih0LCAiLi4vcHJvY2Vzc2VkIGRhdGEvY29ycmVsYXRpb24gZmVhdHVyZXMuY3N2IikKCnRfdCA9IG1lcmdlKHQsIG91dGNvbWUsIGJ5LnggPSAidGVhbSIsIGJ5LnkgPSAiVGVhbSIsIGFsbC54ID0gVFJVRSwgYWxsLnkgPSBUUlVFKQp5ID0gY29sbmFtZXModCkKCmRmX2NvcnIgPSBjb3JyX21hdHJpeCh0X3QsIHhbIXggJWluJSBjKCJmb3JtYXRpb24iKV0sIGMoeVsheSAlaW4lIGMoInRlYW0iLCAibmV3X25hbWUiKV0pKQoKZGZfY29yciRjb3JbZGZfY29yciRwX3ZhbCA+IExvU10gPSBOQQpkZl9jb3JyJGNvciA9IHJvdW5kKGRmX2NvcnIkY29yLCAzKQoKcGx0ID0gZ2dwbG90KGRmX2NvcnIpICsgZ2VvbV90aWxlKGFlcyh4ID0gaiwgeSA9IGksIGZpbGwgPSBjb3IpLCBsd2QgPSAxLjUsIGxpbmV0eXBlID0gMSkgKyBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiYmx1ZSIsIGhpZ2ggPSAicmVkIiwgbmEudmFsdWUgPSAiZ3JleTkwIikgKyB0aGVtZV9idyhiYXNlX3NpemUgPSAxNSkgKyB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArIHlsYWIoIiIpICsgeGxhYigiIikgKyBnZW9tX3RleHQoYWVzKHggPSBqLCB5ID0gaSwgbGFiZWwgPSBjb3IpKSArIGdndGl0bGUoIkNvcnJlbGF0aW9ucyIpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAwLjk1LCB2anVzdCA9IDAuMikpCgpnZ3Bsb3RseShwbHQpCgpnZ3NhdmUocGx0LCBmaWxlbmFtZSA9ICIuLi9maWd1cmVzL2NvcnJlbGF0aW9ucy9zaWdpbmlmaWNhbnRfY29ycmVsYXRpb25zLnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDcpCmBgYAoKClByZS1Gb3JtZWQgdnMgQWxnb3JpdGhtCgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9Cgp0ID0gbWVyZ2UoZGZfa2V5X2F0dHJpYnV0ZXMsIG91dGNvbWUsIGJ5LnggPSAidGVhbSIsIGJ5LnkgPSAiVGVhbSIsIGFsbC54ID0gVFJVRSwgYWxsLnkgPSBUUlVFKQojdCA9IG91dGNvbWUKZGZfdHlwZSA9IGRhdGEuZnJhbWUoKQoKZm9yIChqIGluIGNvbG5hbWVzKHQpKQp7CiAgaWYgKCEgaiAlaW4lIGMoInRlYW0iLCAiVHlwZSIsICJuZXdfbmFtZSIsICJTdGFnZSIsICJmb3JtYXRpb24iLCAiVGVhbSIpKQogIHsKICAgIGRmID0gdFssYygiVHlwZSIsIGopXQogICAgdyA9IHdpbGNveC50ZXN0KGRmW2RmJFR5cGUgPT0gIlByZS1mb3JtZWQiLGpdLCBkZltkZiRUeXBlID09ICJBbGdvcml0aG0iLGpdLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQogICAgc3RhdCA9IG1lYW4oZGZbZGYkVHlwZSA9PSAiUHJlLWZvcm1lZCIsal0sIG5hLnJtID0gVFJVRSkgPiBtZWFuKGRmW2RmJFR5cGUgPT0gIkFsZ29yaXRobSIsal0sIG5hLnJtID0gVFJVRSkKICAgIGRmX3R5cGUgPSByYmluZChkZl90eXBlLCBkYXRhLmZyYW1lKGF0dHJpYnV0ZSA9IGosIHBfdmFsdWUgPSB3JHAudmFsdWUsIGtleSA9IGlmIChzdGF0KSAiUHJlLUZvcm1lZCIgZWxzZSAiQWxnb3JpdGhtIikpCiAgfQp9CgpkZl90eXBlJGtleVtkZl90eXBlJHBfdmFsdWUgPiAwLjFdID0gTkEKCnBsdCA9IGdncGxvdChkZl90eXBlLCBhZXMoeSA9IHJlb3JkZXIoYXR0cmlidXRlLCBwX3ZhbHVlKSwgeCA9IHBfdmFsdWUpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBhZXMoZmlsbCA9IGtleSkpICsgdGhlbWVfYncoYmFzZV9zaXplID0gMTUpICsgeGxhYigiUCBWYWx1ZSIpICsgeWxhYigiIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjEsIGxpbmV0eXBlID0gMiwgY29sb3IgPSAicmVkIikKCmdncGxvdGx5KHBsdCkKCmdnc2F2ZShwbHQsIGZpbGVuYW1lID0gIi4uL2ZpZ3VyZXMvdGVhbV90eXBlLnBuZyIsIGhlaWdodCA9IDEwLCB3aWR0aCA9IDcpCgpgYGAKCmBgYHtyfQoKd3JpdGUuY3N2KG91dGNvbWUsICIuLi9wcm9jZXNzZWQgZGF0YS9jb21wb3NpdGVfb3V0Y29tZS5jc3YiKQojd3JpdGUuY3N2KHJlZywgIi4uL3Byb2Nlc3NlZCBkYXRhL3JlZ19lZGl0ZWQuY3N2IikKCnRlbXAgPSB1bm5lc3QocmVnLCBjb2xzID0gYygiY29tbXVuaWNhdGlvbiIpKQp0ZW1wID0gdGVtcCAlPiUgc2VsZWN0KC0iYmlydGhkYXkiKQp3cml0ZS5jc3YodGVtcCwgZmlsZSA9ICIuLi9wcm9jZXNzZWQgZGF0YS9yZWdfZWRpdGVkLmNzdiIpCgpgYGAKCg==